blob: 0c1a19983811da7581684020092e7e955c20aea6 [file] [log] [blame]
[email protected]23e482282013-06-14 16:08:021// Copyright 2013 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]5285d972011-10-18 18:56:348#include <stdarg.h>
sclittlebe1ccf62015-09-02 19:40:369#include <stdint.h>
danakj1fd259a02016-04-16 03:17:0910
avibf0746c2015-12-09 19:53:1411#include <limits>
rdsmith1d343be52016-10-21 20:37:5012#include <set>
[email protected]5285d972011-10-18 18:56:3413#include <string>
dchengc7eeda422015-12-26 03:56:4814#include <utility>
[email protected]95d88ffe2010-02-04 21:25:3315#include <vector>
[email protected]77848d12008-11-14 00:00:2216
Sebastien Marchand6d0558fd2019-01-25 16:49:3717#include "base/bind.h"
[email protected]68bf9152008-09-25 19:47:3018#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5219#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2920#include "base/files/file_util.h"
[email protected]f3da152d2012-06-02 01:00:5721#include "base/json/json_writer.h"
Adam Rice425cf122015-01-19 06:18:2422#include "base/logging.h"
danakj1fd259a02016-04-16 03:17:0923#include "base/memory/ptr_util.h"
[email protected]bf828982013-08-14 18:01:4724#include "base/memory/weak_ptr.h"
Eric Orthf4db66a2019-02-19 21:35:3325#include "base/optional.h"
[email protected]a34f61ee2014-03-18 20:59:4926#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2427#include "base/stl_util.h"
Bence Békyd74f4382018-02-20 18:26:1928#include "base/strings/string_piece.h"
[email protected]125ef482013-06-11 18:32:4729#include "base/strings/string_util.h"
Matt Menked732ea42019-03-08 12:05:0030#include "base/strings/stringprintf.h"
[email protected]750b2f3c2013-06-07 18:41:0531#include "base/strings/utf_string_conversions.h"
Douglas Creager3cb042052018-11-06 23:08:5232#include "base/test/metrics/histogram_tester.h"
Matt Menke166443c2019-05-24 18:45:5933#include "base/test/scoped_feature_list.h"
Douglas Creager134b52e2018-11-09 18:00:1434#include "base/test/simple_test_clock.h"
35#include "base/test/simple_test_tick_clock.h"
Gabriel Charettec7108742019-08-23 03:31:4036#include "base/test/task_environment.h"
[email protected]f36a8132011-09-02 18:36:3337#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3538#include "base/threading/thread_task_runner_handle.h"
Matt Menke5062be22019-05-01 17:50:2439#include "build/build_config.h"
[email protected]277d5942010-08-11 21:02:3540#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0741#include "net/base/chunked_upload_data_stream.h"
Bence Békya25e3f72018-02-13 21:13:3942#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0743#include "net/base/elements_upload_data_stream.h"
Matt Menke166443c2019-05-24 18:45:5944#include "net/base/features.h"
Eric Orthf4db66a2019-02-19 21:35:3345#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3746#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2547#include "net/base/load_timing_info.h"
48#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2449#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5950#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1551#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4052#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3153#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5254#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1555#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0656#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2157#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0858#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1159#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5360#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2461#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1262#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0063#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2964#include "net/http/http_auth_handler_ntlm.h"
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"
Gabriel Charettec7108742019-08-23 03:31:40111#include "net/test/test_with_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.
Matt Menke6dc08232019-10-03 18:00:28408 FastForwardBy(base::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
bncce36dca22015-04-21 22:11:23506 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54507 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40508
bnc691fda62016-08-12 00:43:16509 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22510 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16511 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22512
bnc691fda62016-08-12 00:43:16513 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47514 return out;
[email protected]ff007e162009-05-23 09:13:15515 }
initial.commit586acc5fe2008-07-26 22:42:52516
Ryan Sleevib8d7ea02018-05-07 20:01:01517 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22518 MockWrite data_writes[] = {
519 MockWrite("GET / HTTP/1.1\r\n"
520 "Host: www.example.org\r\n"
521 "Connection: keep-alive\r\n\r\n"),
522 };
[email protected]5a60c8b2011-10-19 20:14:29523
Ryan Sleevib8d7ea02018-05-07 20:01:01524 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22525 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01526 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22527
Ryan Sleevib8d7ea02018-05-07 20:01:01528 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22529 return out;
[email protected]b8015c42013-12-24 15:18:19530 }
531
bnc032658ba2016-09-26 18:17:15532 void AddSSLSocketData() {
533 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49534 ssl_.ssl_info.cert =
535 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
536 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15537 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
538 }
539
[email protected]ff007e162009-05-23 09:13:15540 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
541 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52542
[email protected]ff007e162009-05-23 09:13:15543 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07544
[email protected]bb88e1d32013-05-03 23:11:07545 void CheckErrorIsPassedBack(int error, IoMode mode);
546
Matt Menked6fd2a52019-03-20 06:14:36547 const CommonConnectJobParams dummy_connect_job_params_;
548
Douglas Creager134b52e2018-11-09 18:00:14549 // These clocks are defined here, even though they're only used in the
550 // Reporting tests below, since they need to be destroyed after
551 // |session_deps_|.
552 base::SimpleTestClock clock_;
553 base::SimpleTestTickClock tick_clock_;
554
[email protected]4bd46222013-05-14 19:32:23555 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07556 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15557 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03558
559 // Original socket limits. Some tests set these. Safest to always restore
560 // them once each test has been run.
561 int old_max_group_sockets_;
562 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15563};
[email protected]231d5a32008-09-13 00:45:27564
[email protected]448d4ca52012-03-04 04:12:23565namespace {
566
ryansturm49a8cb12016-06-15 16:51:09567class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27568 public:
ryansturm49a8cb12016-06-15 16:51:09569 BeforeHeadersSentHandler()
570 : observed_before_headers_sent_with_proxy_(false),
571 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27572
ryansturm49a8cb12016-06-15 16:51:09573 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
574 HttpRequestHeaders* request_headers) {
575 observed_before_headers_sent_ = true;
576 if (!proxy_info.is_http() && !proxy_info.is_https() &&
577 !proxy_info.is_quic()) {
578 return;
579 }
580 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27581 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
582 }
583
ryansturm49a8cb12016-06-15 16:51:09584 bool observed_before_headers_sent_with_proxy() const {
585 return observed_before_headers_sent_with_proxy_;
586 }
587
588 bool observed_before_headers_sent() const {
589 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27590 }
591
592 std::string observed_proxy_server_uri() const {
593 return observed_proxy_server_uri_;
594 }
595
596 private:
ryansturm49a8cb12016-06-15 16:51:09597 bool observed_before_headers_sent_with_proxy_;
598 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27599 std::string observed_proxy_server_uri_;
600
ryansturm49a8cb12016-06-15 16:51:09601 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27602};
603
[email protected]15a5ccf82008-10-23 19:57:43604// Fill |str| with a long header list that consumes >= |size| bytes.
605void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51606 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19607 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
608 const int sizeof_row = strlen(row);
609 const int num_rows = static_cast<int>(
610 ceil(static_cast<float>(size) / sizeof_row));
611 const int sizeof_data = num_rows * sizeof_row;
612 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43613 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51614
[email protected]4ddaf2502008-10-23 18:26:19615 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43616 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19617}
618
thakis84dff942015-07-28 20:47:38619#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09620uint64_t MockGetMSTime() {
621 // Tue, 23 May 2017 20:13:07 +0000
622 return 131400439870000000;
623}
624
[email protected]385a4672009-03-11 22:21:29625// Alternative functions that eliminate randomness and dependency on the local
626// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37627void MockGenerateRandom(uint8_t* output, size_t n) {
628 // This is set to 0xaa because the client challenge for testing in
629 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
630 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29631}
632
[email protected]fe2bc6a2009-03-23 16:52:20633std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37634 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29635}
thakis84dff942015-07-28 20:47:38636#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29637
Matt Menked6fd2a52019-03-20 06:14:36638class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31639 public:
Matt Menked6fd2a52019-03-20 06:14:36640 explicit CaptureGroupIdTransportSocketPool(
641 const CommonConnectJobParams* common_connect_job_params)
642 : TransportClientSocketPool(0,
643 0,
644 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36645 ProxyServer::Direct(),
646 false /* is_for_websockets */,
David Benjamin151ec6b2019-08-02 19:38:52647 common_connect_job_params) {}
[email protected]e60e47a2010-07-14 03:37:18648
Matt Menkef6edce752019-03-19 17:21:56649 const ClientSocketPool::GroupId& last_group_id_received() const {
650 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49651 }
652
Tarun Bansal162eabe52018-01-20 01:16:39653 bool socket_requested() const { return socket_requested_; }
654
Matt Menke28ac03e2019-02-25 22:25:50655 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56656 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03657 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28658 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50659 RequestPriority priority,
660 const SocketTag& socket_tag,
661 ClientSocketPool::RespectLimits respect_limits,
662 ClientSocketHandle* handle,
663 CompletionOnceCallback callback,
664 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
665 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56666 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39667 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31668 return ERR_IO_PENDING;
669 }
Matt Menkef6edce752019-03-19 17:21:56670 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21671 ClientSocketHandle* handle,
672 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56673 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09674 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24675 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57676 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56677 void CloseIdleSocketsInGroup(
678 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57679 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56680 size_t IdleSocketCountInGroup(
681 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31682 return 0;
683 }
Matt Menkef6edce752019-03-19 17:21:56684 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57685 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31686 return LOAD_STATE_IDLE;
687 }
[email protected]d80a4322009-08-14 07:07:49688
689 private:
Matt Menkef6edce752019-03-19 17:21:56690 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39691 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31692};
693
[email protected]231d5a32008-09-13 00:45:27694//-----------------------------------------------------------------------------
695
[email protected]79cb5c12011-09-12 13:12:04696// Helper functions for validating that AuthChallengeInfo's are correctly
697// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58698bool CheckBasicServerAuth(
699 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04700 if (!auth_challenge)
701 return false;
702 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43703 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04704 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19705 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04706 return true;
707}
708
David Benjamin2eb827f2019-04-29 18:31:04709bool CheckBasicSecureServerAuth(
710 const base::Optional<AuthChallengeInfo>& auth_challenge) {
711 if (!auth_challenge)
712 return false;
713 EXPECT_FALSE(auth_challenge->is_proxy);
714 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
715 EXPECT_EQ("MyRealm1", auth_challenge->realm);
716 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
717 return true;
718}
719
Emily Starkf2c9bbd2019-04-09 17:08:58720bool CheckBasicProxyAuth(
721 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04722 if (!auth_challenge)
723 return false;
724 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43725 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
726 EXPECT_EQ("MyRealm1", auth_challenge->realm);
727 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
728 return true;
729}
730
Emily Starkf2c9bbd2019-04-09 17:08:58731bool CheckBasicSecureProxyAuth(
732 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43733 if (!auth_challenge)
734 return false;
735 EXPECT_TRUE(auth_challenge->is_proxy);
736 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04737 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19738 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04739 return true;
740}
741
Emily Starkf2c9bbd2019-04-09 17:08:58742bool CheckDigestServerAuth(
743 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04744 if (!auth_challenge)
745 return false;
746 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43747 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04748 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19749 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04750 return true;
751}
752
thakis84dff942015-07-28 20:47:38753#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58754bool CheckNTLMServerAuth(
755 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04756 if (!auth_challenge)
757 return false;
758 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55759 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04760 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19761 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04762 return true;
763}
David Benjamin5cb91132018-04-06 05:54:49764
Emily Starkf2c9bbd2019-04-09 17:08:58765bool CheckNTLMProxyAuth(
766 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49767 if (!auth_challenge)
768 return false;
769 EXPECT_TRUE(auth_challenge->is_proxy);
770 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
771 EXPECT_EQ(std::string(), auth_challenge->realm);
772 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
773 return true;
774}
thakis84dff942015-07-28 20:47:38775#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04776
[email protected]448d4ca52012-03-04 04:12:23777} // namespace
778
Shivani Sharma8ae506c2019-07-21 21:08:27779// TODO(950069): Add testing for frame_origin in NetworkIsolationKey
780// using kAppendInitiatingFrameOriginToNetworkIsolationKey.
781
bncd16676a2016-07-20 16:23:01782TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09783 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16784 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27785}
786
bncd16676a2016-07-20 16:23:01787TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27788 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35789 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
790 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06791 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27792 };
Ryan Sleevib8d7ea02018-05-07 20:01:01793 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01794 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27795 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
796 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01797 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22798 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47799 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59800
801 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27802}
803
804// Response with no status line.
bncd16676a2016-07-20 16:23:01805TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27806 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35807 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06808 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27809 };
Ryan Sleevib8d7ea02018-05-07 20:01:01810 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41811 EXPECT_THAT(out.rv, IsOk());
812 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
813 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01814 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41815 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27816}
817
mmenkea7da6da2016-09-01 21:56:52818// Response with no status line, and a weird port. Should fail by default.
819TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
820 MockRead data_reads[] = {
821 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
822 };
823
Ryan Sleevib8d7ea02018-05-07 20:01:01824 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52825 session_deps_.socket_factory->AddSocketDataProvider(&data);
826
827 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
828
krasinc06a72a2016-12-21 03:42:46829 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58830 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19831 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52832
mmenkea7da6da2016-09-01 21:56:52833 request.method = "GET";
834 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10835 request.traffic_annotation =
836 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
837
mmenkea7da6da2016-09-01 21:56:52838 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20839 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52840 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
841}
842
Shivani Sharmafdcaefd2017-11-02 00:12:26843// Tests that request info can be destroyed after the headers phase is complete.
844TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
845 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
846 auto trans =
847 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
848
849 MockRead data_reads[] = {
850 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
851 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
852 };
Ryan Sleevib8d7ea02018-05-07 20:01:01853 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26854 session_deps_.socket_factory->AddSocketDataProvider(&data);
855
856 TestCompletionCallback callback;
857
858 {
859 auto request = std::make_unique<HttpRequestInfo>();
860 request->method = "GET";
861 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10862 request->traffic_annotation =
863 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26864
865 int rv =
866 trans->Start(request.get(), callback.callback(), NetLogWithSource());
867
868 EXPECT_THAT(callback.GetResult(rv), IsOk());
869 } // Let request info be destroyed.
870
871 trans.reset();
872}
873
[email protected]231d5a32008-09-13 00:45:27874// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01875TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27876 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35877 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06878 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27879 };
Ryan Sleevib8d7ea02018-05-07 20:01:01880 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01881 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27882 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
883 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01884 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22885 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27886}
887
888// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01889TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27890 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35891 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06892 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27893 };
Ryan Sleevib8d7ea02018-05-07 20:01:01894 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01895 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27896 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
897 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01898 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22899 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27900}
901
902// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01903TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27904 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35905 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06906 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27907 };
Ryan Sleevib8d7ea02018-05-07 20:01:01908 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41909 EXPECT_THAT(out.rv, IsOk());
910 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
911 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01912 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41913 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27914}
915
916// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01917TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27918 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35919 MockRead("\n"),
920 MockRead("\n"),
921 MockRead("Q"),
922 MockRead("J"),
923 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06924 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27925 };
Ryan Sleevib8d7ea02018-05-07 20:01:01926 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01927 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27928 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
929 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01930 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22931 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27932}
933
934// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01935TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27936 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35937 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06938 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27939 };
Ryan Sleevib8d7ea02018-05-07 20:01:01940 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41941 EXPECT_THAT(out.rv, IsOk());
942 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
943 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01944 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41945 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:52946}
947
[email protected]f9d44aa2008-09-23 23:57:17948// Simulate a 204 response, lacking a Content-Length header, sent over a
949// persistent connection. The response should still terminate since a 204
950// cannot have a response body.
bncd16676a2016-07-20 16:23:01951TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19952 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17953 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35954 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19955 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06956 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17957 };
Ryan Sleevib8d7ea02018-05-07 20:01:01958 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01959 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:17960 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
961 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01962 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22963 int64_t response_size = reads_size - strlen(junk);
964 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17965}
966
[email protected]0877e3d2009-10-17 22:29:57967// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:01968TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19969 std::string final_chunk = "0\r\n\r\n";
970 std::string extra_data = "HTTP/1.1 200 OK\r\n";
971 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57972 MockRead data_reads[] = {
973 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
974 MockRead("5\r\nHello\r\n"),
975 MockRead("1\r\n"),
976 MockRead(" \r\n"),
977 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19978 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06979 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57980 };
Ryan Sleevib8d7ea02018-05-07 20:01:01981 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01982 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:57983 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
984 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01985 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22986 int64_t response_size = reads_size - extra_data.size();
987 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57988}
989
[email protected]9fe44f52010-09-23 18:36:00990// Next tests deal with http://crbug.com/56344.
991
bncd16676a2016-07-20 16:23:01992TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00993 MultipleContentLengthHeadersNoTransferEncoding) {
994 MockRead data_reads[] = {
995 MockRead("HTTP/1.1 200 OK\r\n"),
996 MockRead("Content-Length: 10\r\n"),
997 MockRead("Content-Length: 5\r\n\r\n"),
998 };
Ryan Sleevib8d7ea02018-05-07 20:01:01999 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011000 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001001}
1002
bncd16676a2016-07-20 16:23:011003TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041004 DuplicateContentLengthHeadersNoTransferEncoding) {
1005 MockRead data_reads[] = {
1006 MockRead("HTTP/1.1 200 OK\r\n"),
1007 MockRead("Content-Length: 5\r\n"),
1008 MockRead("Content-Length: 5\r\n\r\n"),
1009 MockRead("Hello"),
1010 };
Ryan Sleevib8d7ea02018-05-07 20:01:011011 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011012 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041013 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1014 EXPECT_EQ("Hello", out.response_data);
1015}
1016
bncd16676a2016-07-20 16:23:011017TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041018 ComplexContentLengthHeadersNoTransferEncoding) {
1019 // More than 2 dupes.
1020 {
1021 MockRead data_reads[] = {
1022 MockRead("HTTP/1.1 200 OK\r\n"),
1023 MockRead("Content-Length: 5\r\n"),
1024 MockRead("Content-Length: 5\r\n"),
1025 MockRead("Content-Length: 5\r\n\r\n"),
1026 MockRead("Hello"),
1027 };
Ryan Sleevib8d7ea02018-05-07 20:01:011028 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011029 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041030 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1031 EXPECT_EQ("Hello", out.response_data);
1032 }
1033 // HTTP/1.0
1034 {
1035 MockRead data_reads[] = {
1036 MockRead("HTTP/1.0 200 OK\r\n"),
1037 MockRead("Content-Length: 5\r\n"),
1038 MockRead("Content-Length: 5\r\n"),
1039 MockRead("Content-Length: 5\r\n\r\n"),
1040 MockRead("Hello"),
1041 };
Ryan Sleevib8d7ea02018-05-07 20:01:011042 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011043 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041044 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1045 EXPECT_EQ("Hello", out.response_data);
1046 }
1047 // 2 dupes and one mismatched.
1048 {
1049 MockRead data_reads[] = {
1050 MockRead("HTTP/1.1 200 OK\r\n"),
1051 MockRead("Content-Length: 10\r\n"),
1052 MockRead("Content-Length: 10\r\n"),
1053 MockRead("Content-Length: 5\r\n\r\n"),
1054 };
Ryan Sleevib8d7ea02018-05-07 20:01:011055 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011056 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041057 }
1058}
1059
bncd16676a2016-07-20 16:23:011060TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001061 MultipleContentLengthHeadersTransferEncoding) {
1062 MockRead data_reads[] = {
1063 MockRead("HTTP/1.1 200 OK\r\n"),
1064 MockRead("Content-Length: 666\r\n"),
1065 MockRead("Content-Length: 1337\r\n"),
1066 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1067 MockRead("5\r\nHello\r\n"),
1068 MockRead("1\r\n"),
1069 MockRead(" \r\n"),
1070 MockRead("5\r\nworld\r\n"),
1071 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061072 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001073 };
Ryan Sleevib8d7ea02018-05-07 20:01:011074 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011075 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001076 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1077 EXPECT_EQ("Hello world", out.response_data);
1078}
1079
[email protected]1628fe92011-10-04 23:04:551080// Next tests deal with http://crbug.com/98895.
1081
1082// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011083TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551084 MockRead data_reads[] = {
1085 MockRead("HTTP/1.1 200 OK\r\n"),
1086 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1087 MockRead("Content-Length: 5\r\n\r\n"),
1088 MockRead("Hello"),
1089 };
Ryan Sleevib8d7ea02018-05-07 20:01:011090 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011091 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551092 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1093 EXPECT_EQ("Hello", out.response_data);
1094}
1095
[email protected]54a9c6e52012-03-21 20:10:591096// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011097TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551098 MockRead data_reads[] = {
1099 MockRead("HTTP/1.1 200 OK\r\n"),
1100 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1101 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1102 MockRead("Content-Length: 5\r\n\r\n"),
1103 MockRead("Hello"),
1104 };
Ryan Sleevib8d7ea02018-05-07 20:01:011105 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011106 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591107 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1108 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551109}
1110
1111// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011112TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551113 MockRead data_reads[] = {
1114 MockRead("HTTP/1.1 200 OK\r\n"),
1115 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1116 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1117 MockRead("Content-Length: 5\r\n\r\n"),
1118 MockRead("Hello"),
1119 };
Ryan Sleevib8d7ea02018-05-07 20:01:011120 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011121 EXPECT_THAT(out.rv,
1122 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551123}
1124
[email protected]54a9c6e52012-03-21 20:10:591125// Checks that two identical Location headers result in no error.
1126// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011127TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551128 MockRead data_reads[] = {
1129 MockRead("HTTP/1.1 302 Redirect\r\n"),
1130 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591131 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551132 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061133 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551134 };
1135
1136 HttpRequestInfo request;
1137 request.method = "GET";
1138 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101139 request.traffic_annotation =
1140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551141
danakj1fd259a02016-04-16 03:17:091142 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161143 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551144
Ryan Sleevib8d7ea02018-05-07 20:01:011145 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071146 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551147
[email protected]49639fa2011-12-20 23:22:411148 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551149
tfarina42834112016-09-22 13:38:201150 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011151 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551152
robpercival214763f2016-07-01 23:27:011153 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551154
bnc691fda62016-08-12 00:43:161155 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521156 ASSERT_TRUE(response);
1157 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551158 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1159 std::string url;
1160 EXPECT_TRUE(response->headers->IsRedirect(&url));
1161 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471162 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551163}
1164
[email protected]1628fe92011-10-04 23:04:551165// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011166TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551167 MockRead data_reads[] = {
1168 MockRead("HTTP/1.1 302 Redirect\r\n"),
1169 MockRead("Location: http://good.com/\r\n"),
1170 MockRead("Location: http://evil.com/\r\n"),
1171 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061172 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551173 };
Ryan Sleevib8d7ea02018-05-07 20:01:011174 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011175 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551176}
1177
[email protected]ef0faf2e72009-03-05 23:27:231178// Do a request using the HEAD method. Verify that we don't try to read the
1179// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011180TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421181 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231182 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231183 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101184 request.traffic_annotation =
1185 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231186
danakj1fd259a02016-04-16 03:17:091187 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161188 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091189 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161190 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091191 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1192 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271193
[email protected]ef0faf2e72009-03-05 23:27:231194 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131195 MockWrite("HEAD / HTTP/1.1\r\n"
1196 "Host: www.example.org\r\n"
1197 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231198 };
1199 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231200 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1201 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231202
mmenked39192ee2015-12-09 00:57:231203 // No response body because the test stops reading here.
1204 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231205 };
1206
Ryan Sleevib8d7ea02018-05-07 20:01:011207 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071208 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231209
[email protected]49639fa2011-12-20 23:22:411210 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231211
tfarina42834112016-09-22 13:38:201212 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011213 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231214
1215 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011216 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231217
bnc691fda62016-08-12 00:43:161218 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521219 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231220
1221 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521222 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231223 EXPECT_EQ(1234, response->headers->GetContentLength());
1224 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471225 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091226 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1227 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231228
1229 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101230 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231231 bool has_server_header = response->headers->EnumerateHeader(
1232 &iter, "Server", &server_header);
1233 EXPECT_TRUE(has_server_header);
1234 EXPECT_EQ("Blah", server_header);
1235
1236 // Reading should give EOF right away, since there is no message body
1237 // (despite non-zero content-length).
1238 std::string response_data;
bnc691fda62016-08-12 00:43:161239 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011240 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231241 EXPECT_EQ("", response_data);
1242}
1243
bncd16676a2016-07-20 16:23:011244TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091245 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521246
1247 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351248 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1249 MockRead("hello"),
1250 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1251 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061252 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521253 };
Ryan Sleevib8d7ea02018-05-07 20:01:011254 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071255 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521256
[email protected]0b0bf032010-09-21 18:08:501257 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521258 "hello", "world"
1259 };
1260
1261 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421262 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521263 request.method = "GET";
bncce36dca22015-04-21 22:11:231264 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101265 request.traffic_annotation =
1266 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521267
bnc691fda62016-08-12 00:43:161268 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271269
[email protected]49639fa2011-12-20 23:22:411270 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521271
tfarina42834112016-09-22 13:38:201272 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011273 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521274
1275 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011276 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521277
bnc691fda62016-08-12 00:43:161278 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521279 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521280
wezca1070932016-05-26 20:30:521281 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251282 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471283 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521284
1285 std::string response_data;
bnc691fda62016-08-12 00:43:161286 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011287 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251288 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521289 }
1290}
1291
bncd16676a2016-07-20 16:23:011292TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091293 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221294 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191295 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221296 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271297
[email protected]1c773ea12009-04-28 19:58:421298 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521299 request.method = "POST";
1300 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271301 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101302 request.traffic_annotation =
1303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521304
shivanishab9a143952016-09-19 17:23:411305 // Check the upload progress returned before initialization is correct.
1306 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1307 EXPECT_EQ(0u, progress.size());
1308 EXPECT_EQ(0u, progress.position());
1309
danakj1fd259a02016-04-16 03:17:091310 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161311 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271312
initial.commit586acc5fe2008-07-26 22:42:521313 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351314 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1315 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1316 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061317 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521318 };
Ryan Sleevib8d7ea02018-05-07 20:01:011319 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071320 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521321
[email protected]49639fa2011-12-20 23:22:411322 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521323
tfarina42834112016-09-22 13:38:201324 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521326
1327 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011328 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521329
bnc691fda62016-08-12 00:43:161330 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521331 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521332
wezca1070932016-05-26 20:30:521333 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251334 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521335
1336 std::string response_data;
bnc691fda62016-08-12 00:43:161337 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011338 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251339 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521340}
1341
[email protected]3a2d3662009-03-27 03:49:141342// This test is almost the same as Ignores100 above, but the response contains
1343// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571344// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011345TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421346 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141347 request.method = "GET";
1348 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101349 request.traffic_annotation =
1350 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141351
danakj1fd259a02016-04-16 03:17:091352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161353 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271354
[email protected]3a2d3662009-03-27 03:49:141355 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571356 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1357 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141358 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061359 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141360 };
Ryan Sleevib8d7ea02018-05-07 20:01:011361 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071362 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141363
[email protected]49639fa2011-12-20 23:22:411364 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141365
tfarina42834112016-09-22 13:38:201366 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141368
1369 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011370 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141371
bnc691fda62016-08-12 00:43:161372 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521373 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141374
wezca1070932016-05-26 20:30:521375 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141376 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1377
1378 std::string response_data;
bnc691fda62016-08-12 00:43:161379 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011380 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141381 EXPECT_EQ("hello world", response_data);
1382}
1383
Andrew Comminos517a92c2019-01-14 17:49:561384TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1385 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381386 base::TimeDelta::FromMilliseconds(10);
1387
1388 HttpRequestInfo request;
1389 request.method = "GET";
1390 request.url = GURL("http://www.foo.com/");
1391 request.traffic_annotation =
1392 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1393
1394 std::vector<MockWrite> data_writes = {
1395 MockWrite(ASYNC, 0,
1396 "GET / HTTP/1.1\r\n"
1397 "Host: www.foo.com\r\n"
1398 "Connection: keep-alive\r\n\r\n"),
1399 };
1400
1401 std::vector<MockRead> data_reads = {
1402 // Write one byte of the status line, followed by a pause.
1403 MockRead(ASYNC, 1, "H"),
1404 MockRead(ASYNC, ERR_IO_PENDING, 2),
1405 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1406 MockRead(ASYNC, 4, "hello world"),
1407 MockRead(SYNCHRONOUS, OK, 5),
1408 };
1409
1410 SequencedSocketData data(data_reads, data_writes);
1411 session_deps_.socket_factory->AddSocketDataProvider(&data);
1412
1413 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1414
1415 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1416
1417 TestCompletionCallback callback;
1418
1419 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1420 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1421
1422 data.RunUntilPaused();
1423 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561424 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381425 data.Resume();
1426
1427 rv = callback.WaitForResult();
1428 EXPECT_THAT(rv, IsOk());
1429
1430 const HttpResponseInfo* response = trans.GetResponseInfo();
1431 ASSERT_TRUE(response);
1432
1433 EXPECT_TRUE(response->headers);
1434 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1435
1436 LoadTimingInfo load_timing_info;
1437 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1438 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1439 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561440 // Ensure we didn't include the delay in the TTFB time.
1441 EXPECT_EQ(load_timing_info.receive_headers_start,
1442 load_timing_info.connect_timing.connect_end);
1443 // Ensure that the mock clock advanced at all.
1444 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1445 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381446
1447 std::string response_data;
1448 rv = ReadTransaction(&trans, &response_data);
1449 EXPECT_THAT(rv, IsOk());
1450 EXPECT_EQ("hello world", response_data);
1451}
1452
1453// Tests that the time-to-first-byte reported in a transaction's load timing
1454// info uses the first response, even if 1XX/informational.
1455void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561456 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381457 base::TimeDelta::FromMilliseconds(10);
1458
1459 HttpRequestInfo request;
1460 request.method = "GET";
1461 request.url = GURL("https://www.foo.com/");
1462 request.traffic_annotation =
1463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1464
1465 SSLSocketDataProvider ssl(ASYNC, OK);
1466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1467
1468 std::vector<MockWrite> data_writes;
1469 std::vector<MockRead> data_reads;
1470
1471 spdy::SpdySerializedFrame spdy_req(
1472 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1473
1474 spdy::SpdyHeaderBlock spdy_resp1_headers;
1475 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1476 spdy::SpdySerializedFrame spdy_resp1(
1477 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1478 spdy::SpdySerializedFrame spdy_resp2(
1479 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1480 spdy::SpdySerializedFrame spdy_data(
1481 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1482
1483 if (use_spdy) {
1484 ssl.next_proto = kProtoHTTP2;
1485
1486 data_writes = {CreateMockWrite(spdy_req, 0)};
1487
1488 data_reads = {
1489 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1490 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1491 MockRead(SYNCHRONOUS, OK, 5),
1492 };
1493 } else {
1494 data_writes = {
1495 MockWrite(ASYNC, 0,
1496 "GET / HTTP/1.1\r\n"
1497 "Host: www.foo.com\r\n"
1498 "Connection: keep-alive\r\n\r\n"),
1499 };
1500
1501 data_reads = {
1502 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1503 MockRead(ASYNC, ERR_IO_PENDING, 2),
1504
1505 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1506 MockRead(ASYNC, 4, "hello world"),
1507 MockRead(SYNCHRONOUS, OK, 5),
1508 };
1509 }
1510
1511 SequencedSocketData data(data_reads, data_writes);
1512 session_deps_.socket_factory->AddSocketDataProvider(&data);
1513
1514 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1515
1516 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1517
1518 TestCompletionCallback callback;
1519
1520 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1521 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1522
1523 data.RunUntilPaused();
1524 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1525 // the delay before parsing the 200 response.
1526 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561527 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381528 data.Resume();
1529
1530 rv = callback.WaitForResult();
1531 EXPECT_THAT(rv, IsOk());
1532
1533 const HttpResponseInfo* response = trans.GetResponseInfo();
1534 ASSERT_TRUE(response);
1535
1536 LoadTimingInfo load_timing_info;
1537 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1538 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1539 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561540 // Ensure we didn't include the delay in the TTFB time.
1541 EXPECT_EQ(load_timing_info.receive_headers_start,
1542 load_timing_info.connect_timing.connect_end);
1543 // Ensure that the mock clock advanced at all.
1544 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1545 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381546
1547 std::string response_data;
1548 rv = ReadTransaction(&trans, &response_data);
1549 EXPECT_THAT(rv, IsOk());
1550 EXPECT_EQ("hello world", response_data);
1551}
1552
Andrew Comminos517a92c2019-01-14 17:49:561553TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381554 Check100ResponseTiming(false /* use_spdy */);
1555}
1556
Andrew Comminos517a92c2019-01-14 17:49:561557TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381558 Check100ResponseTiming(true /* use_spdy */);
1559}
1560
bncd16676a2016-07-20 16:23:011561TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081562 HttpRequestInfo request;
1563 request.method = "POST";
1564 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101565 request.traffic_annotation =
1566 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081567
danakj1fd259a02016-04-16 03:17:091568 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081570
1571 MockRead data_reads[] = {
1572 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1573 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381574 };
Ryan Sleevib8d7ea02018-05-07 20:01:011575 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081576 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381577
zmo9528c9f42015-08-04 22:12:081578 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381579
tfarina42834112016-09-22 13:38:201580 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011581 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381582
zmo9528c9f42015-08-04 22:12:081583 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011584 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381585
zmo9528c9f42015-08-04 22:12:081586 std::string response_data;
bnc691fda62016-08-12 00:43:161587 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011588 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081589 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381590}
1591
bncd16676a2016-07-20 16:23:011592TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381593 HttpRequestInfo request;
1594 request.method = "POST";
1595 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101596 request.traffic_annotation =
1597 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381598
danakj1fd259a02016-04-16 03:17:091599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161600 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271601
[email protected]ee9410e72010-01-07 01:42:381602 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061603 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381604 };
Ryan Sleevib8d7ea02018-05-07 20:01:011605 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071606 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381607
[email protected]49639fa2011-12-20 23:22:411608 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381609
tfarina42834112016-09-22 13:38:201610 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011611 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381612
1613 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011614 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381615}
1616
[email protected]23e482282013-06-14 16:08:021617void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511618 const MockWrite* write_failure,
1619 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421620 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521621 request.method = "GET";
1622 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101623 request.traffic_annotation =
1624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521625
vishal.b62985ca92015-04-17 08:45:511626 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071627 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271629
[email protected]202965992011-12-07 23:04:511630 // Written data for successfully sending both requests.
1631 MockWrite data1_writes[] = {
1632 MockWrite("GET / HTTP/1.1\r\n"
1633 "Host: www.foo.com\r\n"
1634 "Connection: keep-alive\r\n\r\n"),
1635 MockWrite("GET / HTTP/1.1\r\n"
1636 "Host: www.foo.com\r\n"
1637 "Connection: keep-alive\r\n\r\n")
1638 };
1639
1640 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521641 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351642 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1643 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061644 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521645 };
[email protected]202965992011-12-07 23:04:511646
1647 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491648 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511649 data1_writes[1] = *write_failure;
1650 } else {
1651 ASSERT_TRUE(read_failure);
1652 data1_reads[2] = *read_failure;
1653 }
1654
Ryan Sleevib8d7ea02018-05-07 20:01:011655 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071656 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521657
1658 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351659 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1660 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061661 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521662 };
Ryan Sleevib8d7ea02018-05-07 20:01:011663 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071664 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521665
thestig9d3bb0c2015-01-24 00:49:511666 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521667 "hello", "world"
1668 };
1669
mikecironef22f9812016-10-04 03:40:191670 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521671 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411672 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521673
bnc691fda62016-08-12 00:43:161674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521675
tfarina42834112016-09-22 13:38:201676 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521678
1679 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011680 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521681
[email protected]58e32bb2013-01-21 18:23:251682 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161683 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251684 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1685 if (i == 0) {
1686 first_socket_log_id = load_timing_info.socket_log_id;
1687 } else {
1688 // The second request should be using a new socket.
1689 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1690 }
1691
bnc691fda62016-08-12 00:43:161692 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521693 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521694
wezca1070932016-05-26 20:30:521695 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471696 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251697 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521698
1699 std::string response_data;
bnc691fda62016-08-12 00:43:161700 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011701 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251702 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521703 }
1704}
[email protected]3d2a59b2008-09-26 19:44:251705
[email protected]a34f61ee2014-03-18 20:59:491706void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1707 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101708 const MockRead* read_failure,
1709 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491710 HttpRequestInfo request;
1711 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101712 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101713 request.traffic_annotation =
1714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491715
vishal.b62985ca92015-04-17 08:45:511716 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491717 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491719
[email protected]09356c652014-03-25 15:36:101720 SSLSocketDataProvider ssl1(ASYNC, OK);
1721 SSLSocketDataProvider ssl2(ASYNC, OK);
1722 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361723 ssl1.next_proto = kProtoHTTP2;
1724 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101725 }
1726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491728
[email protected]09356c652014-03-25 15:36:101729 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131730 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491731 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131732 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351733 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131734 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191735 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491736
[email protected]09356c652014-03-25 15:36:101737 // HTTP/1.1 versions of the request and response.
1738 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1739 "Host: www.foo.com\r\n"
1740 "Connection: keep-alive\r\n\r\n";
1741 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1742 const char kHttpData[] = "hello";
1743
1744 std::vector<MockRead> data1_reads;
1745 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491746 if (write_failure) {
1747 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101748 data1_writes.push_back(*write_failure);
1749 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491750 } else {
1751 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101752 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411753 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101754 } else {
1755 data1_writes.push_back(MockWrite(kHttpRequest));
1756 }
1757 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491758 }
1759
Ryan Sleevib8d7ea02018-05-07 20:01:011760 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491761 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1762
[email protected]09356c652014-03-25 15:36:101763 std::vector<MockRead> data2_reads;
1764 std::vector<MockWrite> data2_writes;
1765
1766 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411767 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101768
bncdf80d44fd2016-07-15 20:27:411769 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1770 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101771 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1772 } else {
1773 data2_writes.push_back(
1774 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1775
1776 data2_reads.push_back(
1777 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1778 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1779 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1780 }
Ryan Sleevib8d7ea02018-05-07 20:01:011781 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491782 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1783
1784 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591785 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491786 // Wait for the preconnect to complete.
1787 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1788 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231789 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491790
1791 // Make the request.
1792 TestCompletionCallback callback;
1793
bnc691fda62016-08-12 00:43:161794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491795
tfarina42834112016-09-22 13:38:201796 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011797 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491798
1799 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011800 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491801
1802 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161803 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101804 TestLoadTimingNotReused(
1805 load_timing_info,
1806 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491807
bnc691fda62016-08-12 00:43:161808 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521809 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491810
wezca1070932016-05-26 20:30:521811 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021812 if (response->was_fetched_via_spdy) {
1813 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1814 } else {
1815 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1816 }
[email protected]a34f61ee2014-03-18 20:59:491817
1818 std::string response_data;
bnc691fda62016-08-12 00:43:161819 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011820 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101821 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491822}
1823
Biljith Jayan45a41722017-08-16 18:43:141824// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181825// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141826// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1827TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1828 HttpRequestInfo request;
1829 request.method = "GET";
1830 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101831 request.traffic_annotation =
1832 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141833
1834 // Check whether we give up after the third try.
1835
1836 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131837 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141838 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131839 spdy::SpdySerializedFrame spdy_response_go_away(
1840 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011841 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1842 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141843
1844 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011845 StaticSocketDataProvider data1(data_read1, data_write);
1846 StaticSocketDataProvider data2(data_read1, data_write);
1847 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141848
1849 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1850 AddSSLSocketData();
1851 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1852 AddSSLSocketData();
1853 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1854 AddSSLSocketData();
1855
1856 TestCompletionCallback callback;
1857 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1858 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1859
1860 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1861 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1862
1863 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181864 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141865}
1866
1867TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1868 HttpRequestInfo request;
1869 request.method = "GET";
1870 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101871 request.traffic_annotation =
1872 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141873
1874 // Check whether we try atleast thrice before giving up.
1875
1876 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131877 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141878 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131879 spdy::SpdySerializedFrame spdy_response_go_away(
1880 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011881 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1882 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141883
1884 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131885 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141886 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131887 spdy::SpdySerializedFrame spdy_data(
1888 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141889 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1890 CreateMockRead(spdy_data, 2)};
1891
1892 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011893 StaticSocketDataProvider data1(data_read1, data_write);
1894 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141895 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011896 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141897
1898 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1899 AddSSLSocketData();
1900 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1901 AddSSLSocketData();
1902 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1903 AddSSLSocketData();
1904
1905 TestCompletionCallback callback;
1906 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1907 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1908
1909 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1910 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1911
1912 rv = callback.WaitForResult();
1913 EXPECT_THAT(rv, IsOk());
1914}
1915
bncd16676a2016-07-20 16:23:011916TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061917 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351918 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511919}
1920
bncd16676a2016-07-20 16:23:011921TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061922 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351923 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251924}
1925
bncd16676a2016-07-20 16:23:011926TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061927 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351928 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251929}
1930
[email protected]d58ceea82014-06-04 10:55:541931// Make sure that on a 408 response (Request Timeout), the request is retried,
1932// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011933TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541934 MockRead read_failure(SYNCHRONOUS,
1935 "HTTP/1.1 408 Request Timeout\r\n"
1936 "Connection: Keep-Alive\r\n"
1937 "Content-Length: 6\r\n\r\n"
1938 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351939 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541940}
1941
bncd16676a2016-07-20 16:23:011942TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491943 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351944 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:491945}
1946
bncd16676a2016-07-20 16:23:011947TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491948 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351949 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491950}
1951
bncd16676a2016-07-20 16:23:011952TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491953 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351954 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101955}
1956
bncd16676a2016-07-20 16:23:011957TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101958 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351959 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:101960}
1961
[email protected]d58ceea82014-06-04 10:55:541962// Make sure that on a 408 response (Request Timeout), the request is retried,
1963// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:011964TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:541965 MockRead read_failure(SYNCHRONOUS,
1966 "HTTP/1.1 408 Request Timeout\r\n"
1967 "Connection: Keep-Alive\r\n"
1968 "Content-Length: 6\r\n\r\n"
1969 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351970 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
1971 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:541972}
1973
bncd16676a2016-07-20 16:23:011974TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:101975 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351976 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:101977}
1978
bncd16676a2016-07-20 16:23:011979TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:101980 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351981 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101982}
1983
bncd16676a2016-07-20 16:23:011984TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:101985 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351986 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:101987}
1988
bncd16676a2016-07-20 16:23:011989TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101990 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351991 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491992}
1993
bncd16676a2016-07-20 16:23:011994TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421995 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251996 request.method = "GET";
bncce36dca22015-04-21 22:11:231997 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101998 request.traffic_annotation =
1999 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252000
danakj1fd259a02016-04-16 03:17:092001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162002 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272003
[email protected]3d2a59b2008-09-26 19:44:252004 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062005 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352006 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2007 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062008 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252009 };
Ryan Sleevib8d7ea02018-05-07 20:01:012010 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072011 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252012
[email protected]49639fa2011-12-20 23:22:412013 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252014
tfarina42834112016-09-22 13:38:202015 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012016 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252017
2018 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012019 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592020
2021 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162022 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592023 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252024}
2025
2026// What do various browsers do when the server closes a non-keepalive
2027// connection without sending any response header or body?
2028//
2029// IE7: error page
2030// Safari 3.1.2 (Windows): error page
2031// Firefox 3.0.1: blank page
2032// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422033// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2034// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012035TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252036 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062037 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352038 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2039 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062040 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252041 };
Ryan Sleevib8d7ea02018-05-07 20:01:012042 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012043 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252044}
[email protected]1826a402014-01-08 15:40:482045
[email protected]7a5378b2012-11-04 03:25:172046// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2047// tests. There was a bug causing HttpNetworkTransaction to hang in the
2048// destructor in such situations.
2049// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012050TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172051 HttpRequestInfo request;
2052 request.method = "GET";
bncce36dca22015-04-21 22:11:232053 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102054 request.traffic_annotation =
2055 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172056
danakj1fd259a02016-04-16 03:17:092057 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582058 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192059 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172060
2061 MockRead data_reads[] = {
2062 MockRead("HTTP/1.0 200 OK\r\n"),
2063 MockRead("Connection: keep-alive\r\n"),
2064 MockRead("Content-Length: 100\r\n\r\n"),
2065 MockRead("hello"),
2066 MockRead(SYNCHRONOUS, 0),
2067 };
Ryan Sleevib8d7ea02018-05-07 20:01:012068 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072069 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172070
2071 TestCompletionCallback callback;
2072
tfarina42834112016-09-22 13:38:202073 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012074 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172075
2076 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012077 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172078
Victor Costan9c7302b2018-08-27 16:39:442079 scoped_refptr<IOBufferWithSize> io_buf =
2080 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502081 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172082 if (rv == ERR_IO_PENDING)
2083 rv = callback.WaitForResult();
2084 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502085 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012086 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172087
2088 trans.reset();
fdoray92e35a72016-06-10 15:54:552089 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172090 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2091}
2092
bncd16676a2016-07-20 16:23:012093TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172094 HttpRequestInfo request;
2095 request.method = "GET";
bncce36dca22015-04-21 22:11:232096 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102097 request.traffic_annotation =
2098 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172099
danakj1fd259a02016-04-16 03:17:092100 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582101 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192102 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172103
2104 MockRead data_reads[] = {
2105 MockRead("HTTP/1.0 200 OK\r\n"),
2106 MockRead("Connection: keep-alive\r\n"),
2107 MockRead("Content-Length: 100\r\n\r\n"),
2108 MockRead(SYNCHRONOUS, 0),
2109 };
Ryan Sleevib8d7ea02018-05-07 20:01:012110 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072111 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172112
2113 TestCompletionCallback callback;
2114
tfarina42834112016-09-22 13:38:202115 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012116 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172117
2118 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012119 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172120
Victor Costan9c7302b2018-08-27 16:39:442121 scoped_refptr<IOBufferWithSize> io_buf(
2122 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502123 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172124 if (rv == ERR_IO_PENDING)
2125 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012126 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172127
2128 trans.reset();
fdoray92e35a72016-06-10 15:54:552129 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172130 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2131}
2132
[email protected]0b0bf032010-09-21 18:08:502133// Test that we correctly reuse a keep-alive connection after not explicitly
2134// reading the body.
bncd16676a2016-07-20 16:23:012135TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132136 HttpRequestInfo request;
2137 request.method = "GET";
2138 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102139 request.traffic_annotation =
2140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132141
vishal.b62985ca92015-04-17 08:45:512142 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072143 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092144 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272145
mmenkecc2298e2015-12-07 18:20:182146 const char* request_data =
2147 "GET / HTTP/1.1\r\n"
2148 "Host: www.foo.com\r\n"
2149 "Connection: keep-alive\r\n\r\n";
2150 MockWrite data_writes[] = {
2151 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2152 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2153 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2154 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2155 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2156 };
2157
[email protected]0b0bf032010-09-21 18:08:502158 // Note that because all these reads happen in the same
2159 // StaticSocketDataProvider, it shows that the same socket is being reused for
2160 // all transactions.
mmenkecc2298e2015-12-07 18:20:182161 MockRead data_reads[] = {
2162 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2163 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2164 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2165 MockRead(ASYNC, 7,
2166 "HTTP/1.1 302 Found\r\n"
2167 "Content-Length: 0\r\n\r\n"),
2168 MockRead(ASYNC, 9,
2169 "HTTP/1.1 302 Found\r\n"
2170 "Content-Length: 5\r\n\r\n"
2171 "hello"),
2172 MockRead(ASYNC, 11,
2173 "HTTP/1.1 301 Moved Permanently\r\n"
2174 "Content-Length: 0\r\n\r\n"),
2175 MockRead(ASYNC, 13,
2176 "HTTP/1.1 301 Moved Permanently\r\n"
2177 "Content-Length: 5\r\n\r\n"
2178 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132179
mmenkecc2298e2015-12-07 18:20:182180 // In the next two rounds, IsConnectedAndIdle returns false, due to
2181 // the set_busy_before_sync_reads(true) call, while the
2182 // HttpNetworkTransaction is being shut down, but the socket is still
2183 // reuseable. See http://crbug.com/544255.
2184 MockRead(ASYNC, 15,
2185 "HTTP/1.1 200 Hunky-Dory\r\n"
2186 "Content-Length: 5\r\n\r\n"),
2187 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132188
mmenkecc2298e2015-12-07 18:20:182189 MockRead(ASYNC, 18,
2190 "HTTP/1.1 200 Hunky-Dory\r\n"
2191 "Content-Length: 5\r\n\r\n"
2192 "he"),
2193 MockRead(SYNCHRONOUS, 19, "llo"),
2194
2195 // The body of the final request is actually read.
2196 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2197 MockRead(ASYNC, 22, "hello"),
2198 };
Ryan Sleevib8d7ea02018-05-07 20:01:012199 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182200 data.set_busy_before_sync_reads(true);
2201 session_deps_.socket_factory->AddSocketDataProvider(&data);
2202
Avi Drissman4365a4782018-12-28 19:26:242203 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502204 std::string response_lines[kNumUnreadBodies];
2205
mikecironef22f9812016-10-04 03:40:192206 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182207 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412208 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132209
Jeremy Roman0579ed62017-08-29 15:56:192210 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582211 session.get());
[email protected]fc31d6a42010-06-24 18:05:132212
tfarina42834112016-09-22 13:38:202213 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012214 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132215
[email protected]58e32bb2013-01-21 18:23:252216 LoadTimingInfo load_timing_info;
2217 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2218 if (i == 0) {
2219 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2220 first_socket_log_id = load_timing_info.socket_log_id;
2221 } else {
2222 TestLoadTimingReused(load_timing_info);
2223 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2224 }
2225
[email protected]fc31d6a42010-06-24 18:05:132226 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182227 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132228
mmenkecc2298e2015-12-07 18:20:182229 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502230 response_lines[i] = response->headers->GetStatusLine();
2231
mmenkecc2298e2015-12-07 18:20:182232 // Delete the transaction without reading the response bodies. Then spin
2233 // the message loop, so the response bodies are drained.
2234 trans.reset();
2235 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132236 }
[email protected]0b0bf032010-09-21 18:08:502237
2238 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182239 "HTTP/1.1 204 No Content",
2240 "HTTP/1.1 205 Reset Content",
2241 "HTTP/1.1 304 Not Modified",
2242 "HTTP/1.1 302 Found",
2243 "HTTP/1.1 302 Found",
2244 "HTTP/1.1 301 Moved Permanently",
2245 "HTTP/1.1 301 Moved Permanently",
2246 "HTTP/1.1 200 Hunky-Dory",
2247 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502248 };
2249
Avi Drissman4365a4782018-12-28 19:26:242250 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272251 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502252
2253 for (int i = 0; i < kNumUnreadBodies; ++i)
2254 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2255
[email protected]49639fa2011-12-20 23:22:412256 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162257 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202258 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012259 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162260 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182261 ASSERT_TRUE(response);
2262 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2264 std::string response_data;
bnc691fda62016-08-12 00:43:162265 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012266 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502267 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132268}
2269
mmenke5f94fda2016-06-02 20:54:132270// Sockets that receive extra data after a response is complete should not be
2271// reused.
bncd16676a2016-07-20 16:23:012272TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132273 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2274 MockWrite data_writes1[] = {
2275 MockWrite("HEAD / HTTP/1.1\r\n"
2276 "Host: www.borked.com\r\n"
2277 "Connection: keep-alive\r\n\r\n"),
2278 };
2279
2280 MockRead data_reads1[] = {
2281 MockRead("HTTP/1.1 200 OK\r\n"
2282 "Connection: keep-alive\r\n"
2283 "Content-Length: 22\r\n\r\n"
2284 "This server is borked."),
2285 };
2286
2287 MockWrite data_writes2[] = {
2288 MockWrite("GET /foo HTTP/1.1\r\n"
2289 "Host: www.borked.com\r\n"
2290 "Connection: keep-alive\r\n\r\n"),
2291 };
2292
2293 MockRead data_reads2[] = {
2294 MockRead("HTTP/1.1 200 OK\r\n"
2295 "Content-Length: 3\r\n\r\n"
2296 "foo"),
2297 };
Ryan Sleevib8d7ea02018-05-07 20:01:012298 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132299 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012300 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132301 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2302
2303 TestCompletionCallback callback;
2304 HttpRequestInfo request1;
2305 request1.method = "HEAD";
2306 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102307 request1.traffic_annotation =
2308 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132309
bnc87dcefc2017-05-25 12:47:582310 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192311 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202312 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012313 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132314
2315 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2316 ASSERT_TRUE(response1);
2317 ASSERT_TRUE(response1->headers);
2318 EXPECT_EQ(200, response1->headers->response_code());
2319 EXPECT_TRUE(response1->headers->IsKeepAlive());
2320
2321 std::string response_data1;
robpercival214763f2016-07-01 23:27:012322 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132323 EXPECT_EQ("", response_data1);
2324 // Deleting the transaction attempts to release the socket back into the
2325 // socket pool.
2326 trans1.reset();
2327
2328 HttpRequestInfo request2;
2329 request2.method = "GET";
2330 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102331 request2.traffic_annotation =
2332 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132333
bnc87dcefc2017-05-25 12:47:582334 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192335 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202336 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012337 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132338
2339 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2340 ASSERT_TRUE(response2);
2341 ASSERT_TRUE(response2->headers);
2342 EXPECT_EQ(200, response2->headers->response_code());
2343
2344 std::string response_data2;
robpercival214763f2016-07-01 23:27:012345 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132346 EXPECT_EQ("foo", response_data2);
2347}
2348
bncd16676a2016-07-20 16:23:012349TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132350 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2351 MockWrite data_writes1[] = {
2352 MockWrite("GET / HTTP/1.1\r\n"
2353 "Host: www.borked.com\r\n"
2354 "Connection: keep-alive\r\n\r\n"),
2355 };
2356
2357 MockRead data_reads1[] = {
2358 MockRead("HTTP/1.1 200 OK\r\n"
2359 "Connection: keep-alive\r\n"
2360 "Content-Length: 22\r\n\r\n"
2361 "This server is borked."
2362 "Bonus data!"),
2363 };
2364
2365 MockWrite data_writes2[] = {
2366 MockWrite("GET /foo HTTP/1.1\r\n"
2367 "Host: www.borked.com\r\n"
2368 "Connection: keep-alive\r\n\r\n"),
2369 };
2370
2371 MockRead data_reads2[] = {
2372 MockRead("HTTP/1.1 200 OK\r\n"
2373 "Content-Length: 3\r\n\r\n"
2374 "foo"),
2375 };
Ryan Sleevib8d7ea02018-05-07 20:01:012376 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132377 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012378 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132379 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2380
2381 TestCompletionCallback callback;
2382 HttpRequestInfo request1;
2383 request1.method = "GET";
2384 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102385 request1.traffic_annotation =
2386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132387
bnc87dcefc2017-05-25 12:47:582388 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192389 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202390 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012391 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132392
2393 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2394 ASSERT_TRUE(response1);
2395 ASSERT_TRUE(response1->headers);
2396 EXPECT_EQ(200, response1->headers->response_code());
2397 EXPECT_TRUE(response1->headers->IsKeepAlive());
2398
2399 std::string response_data1;
robpercival214763f2016-07-01 23:27:012400 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132401 EXPECT_EQ("This server is borked.", response_data1);
2402 // Deleting the transaction attempts to release the socket back into the
2403 // socket pool.
2404 trans1.reset();
2405
2406 HttpRequestInfo request2;
2407 request2.method = "GET";
2408 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102409 request2.traffic_annotation =
2410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132411
bnc87dcefc2017-05-25 12:47:582412 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192413 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202414 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012415 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132416
2417 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2418 ASSERT_TRUE(response2);
2419 ASSERT_TRUE(response2->headers);
2420 EXPECT_EQ(200, response2->headers->response_code());
2421
2422 std::string response_data2;
robpercival214763f2016-07-01 23:27:012423 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132424 EXPECT_EQ("foo", response_data2);
2425}
2426
bncd16676a2016-07-20 16:23:012427TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132428 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2429 MockWrite data_writes1[] = {
2430 MockWrite("GET / HTTP/1.1\r\n"
2431 "Host: www.borked.com\r\n"
2432 "Connection: keep-alive\r\n\r\n"),
2433 };
2434
2435 MockRead data_reads1[] = {
2436 MockRead("HTTP/1.1 200 OK\r\n"
2437 "Connection: keep-alive\r\n"
2438 "Transfer-Encoding: chunked\r\n\r\n"),
2439 MockRead("16\r\nThis server is borked.\r\n"),
2440 MockRead("0\r\n\r\nBonus data!"),
2441 };
2442
2443 MockWrite data_writes2[] = {
2444 MockWrite("GET /foo HTTP/1.1\r\n"
2445 "Host: www.borked.com\r\n"
2446 "Connection: keep-alive\r\n\r\n"),
2447 };
2448
2449 MockRead data_reads2[] = {
2450 MockRead("HTTP/1.1 200 OK\r\n"
2451 "Content-Length: 3\r\n\r\n"
2452 "foo"),
2453 };
Ryan Sleevib8d7ea02018-05-07 20:01:012454 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132455 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012456 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132457 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2458
2459 TestCompletionCallback callback;
2460 HttpRequestInfo request1;
2461 request1.method = "GET";
2462 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102463 request1.traffic_annotation =
2464 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132465
bnc87dcefc2017-05-25 12:47:582466 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192467 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202468 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012469 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132470
2471 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2472 ASSERT_TRUE(response1);
2473 ASSERT_TRUE(response1->headers);
2474 EXPECT_EQ(200, response1->headers->response_code());
2475 EXPECT_TRUE(response1->headers->IsKeepAlive());
2476
2477 std::string response_data1;
robpercival214763f2016-07-01 23:27:012478 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132479 EXPECT_EQ("This server is borked.", response_data1);
2480 // Deleting the transaction attempts to release the socket back into the
2481 // socket pool.
2482 trans1.reset();
2483
2484 HttpRequestInfo request2;
2485 request2.method = "GET";
2486 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102487 request2.traffic_annotation =
2488 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132489
bnc87dcefc2017-05-25 12:47:582490 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192491 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202492 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012493 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132494
2495 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2496 ASSERT_TRUE(response2);
2497 ASSERT_TRUE(response2->headers);
2498 EXPECT_EQ(200, response2->headers->response_code());
2499
2500 std::string response_data2;
robpercival214763f2016-07-01 23:27:012501 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132502 EXPECT_EQ("foo", response_data2);
2503}
2504
2505// This is a little different from the others - it tests the case that the
2506// HttpStreamParser doesn't know if there's extra data on a socket or not when
2507// the HttpNetworkTransaction is torn down, because the response body hasn't
2508// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012509TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132510 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2511 MockWrite data_writes1[] = {
2512 MockWrite("GET / HTTP/1.1\r\n"
2513 "Host: www.borked.com\r\n"
2514 "Connection: keep-alive\r\n\r\n"),
2515 };
2516
2517 MockRead data_reads1[] = {
2518 MockRead("HTTP/1.1 200 OK\r\n"
2519 "Connection: keep-alive\r\n"
2520 "Transfer-Encoding: chunked\r\n\r\n"),
2521 MockRead("16\r\nThis server is borked.\r\n"),
2522 MockRead("0\r\n\r\nBonus data!"),
2523 };
Ryan Sleevib8d7ea02018-05-07 20:01:012524 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132525 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2526
2527 TestCompletionCallback callback;
2528 HttpRequestInfo request1;
2529 request1.method = "GET";
2530 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102531 request1.traffic_annotation =
2532 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132533
bnc87dcefc2017-05-25 12:47:582534 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192535 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582536 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012537 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132538
bnc87dcefc2017-05-25 12:47:582539 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132540 ASSERT_TRUE(response1);
2541 ASSERT_TRUE(response1->headers);
2542 EXPECT_EQ(200, response1->headers->response_code());
2543 EXPECT_TRUE(response1->headers->IsKeepAlive());
2544
2545 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2546 // response body.
bnc87dcefc2017-05-25 12:47:582547 trans.reset();
mmenke5f94fda2016-06-02 20:54:132548
2549 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2550 // socket can't be reused, rather than returning it to the socket pool.
2551 base::RunLoop().RunUntilIdle();
2552
2553 // There should be no idle sockets in the pool.
2554 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2555}
2556
[email protected]038e9a32008-10-08 22:40:162557// Test the request-challenge-retry sequence for basic auth.
2558// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012559TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422560 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162561 request.method = "GET";
bncce36dca22015-04-21 22:11:232562 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102563 request.traffic_annotation =
2564 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162565
vishal.b62985ca92015-04-17 08:45:512566 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072567 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092568 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272570
[email protected]f9ee6b52008-11-08 06:46:232571 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232572 MockWrite(
2573 "GET / HTTP/1.1\r\n"
2574 "Host: www.example.org\r\n"
2575 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232576 };
2577
[email protected]038e9a32008-10-08 22:40:162578 MockRead data_reads1[] = {
2579 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2580 // Give a couple authenticate options (only the middle one is actually
2581 // supported).
[email protected]22927ad2009-09-21 19:56:192582 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162583 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2584 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2585 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2586 // Large content-length -- won't matter, as connection will be reset.
2587 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062588 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162589 };
2590
2591 // After calling trans->RestartWithAuth(), this is the request we should
2592 // be issuing -- the final header line contains the credentials.
2593 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232594 MockWrite(
2595 "GET / HTTP/1.1\r\n"
2596 "Host: www.example.org\r\n"
2597 "Connection: keep-alive\r\n"
2598 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162599 };
2600
2601 // Lastly, the server responds with the actual content.
2602 MockRead data_reads2[] = {
2603 MockRead("HTTP/1.0 200 OK\r\n"),
2604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2605 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062606 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162607 };
2608
Ryan Sleevib8d7ea02018-05-07 20:01:012609 StaticSocketDataProvider data1(data_reads1, data_writes1);
2610 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072611 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2612 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162613
[email protected]49639fa2011-12-20 23:22:412614 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162615
tfarina42834112016-09-22 13:38:202616 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012617 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162618
2619 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012620 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162621
[email protected]58e32bb2013-01-21 18:23:252622 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162623 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252624 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2625
Ryan Sleevib8d7ea02018-05-07 20:01:012626 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162627 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012628 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162629 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192630
bnc691fda62016-08-12 00:43:162631 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522632 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582633 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162634
[email protected]49639fa2011-12-20 23:22:412635 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162636
bnc691fda62016-08-12 00:43:162637 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012638 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162639
2640 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012641 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162642
[email protected]58e32bb2013-01-21 18:23:252643 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162644 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252645 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2646 // The load timing after restart should have a new socket ID, and times after
2647 // those of the first load timing.
2648 EXPECT_LE(load_timing_info1.receive_headers_end,
2649 load_timing_info2.connect_timing.connect_start);
2650 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2651
Ryan Sleevib8d7ea02018-05-07 20:01:012652 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162653 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012654 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162655 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192656
bnc691fda62016-08-12 00:43:162657 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522658 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582659 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162660 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162661}
2662
ttuttled9dbc652015-09-29 20:00:592663// Test the request-challenge-retry sequence for basic auth.
2664// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012665TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592666 HttpRequestInfo request;
2667 request.method = "GET";
2668 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102669 request.traffic_annotation =
2670 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592671
2672 TestNetLog log;
2673 MockHostResolver* resolver = new MockHostResolver();
2674 session_deps_.net_log = &log;
2675 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092676 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162677 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592678
2679 resolver->rules()->ClearRules();
2680 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2681
2682 MockWrite data_writes1[] = {
2683 MockWrite("GET / HTTP/1.1\r\n"
2684 "Host: www.example.org\r\n"
2685 "Connection: keep-alive\r\n\r\n"),
2686 };
2687
2688 MockRead data_reads1[] = {
2689 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2690 // Give a couple authenticate options (only the middle one is actually
2691 // supported).
2692 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2693 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2694 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2695 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2696 // Large content-length -- won't matter, as connection will be reset.
2697 MockRead("Content-Length: 10000\r\n\r\n"),
2698 MockRead(SYNCHRONOUS, ERR_FAILED),
2699 };
2700
2701 // After calling trans->RestartWithAuth(), this is the request we should
2702 // be issuing -- the final header line contains the credentials.
2703 MockWrite data_writes2[] = {
2704 MockWrite("GET / HTTP/1.1\r\n"
2705 "Host: www.example.org\r\n"
2706 "Connection: keep-alive\r\n"
2707 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2708 };
2709
2710 // Lastly, the server responds with the actual content.
2711 MockRead data_reads2[] = {
2712 MockRead("HTTP/1.0 200 OK\r\n"),
2713 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2714 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2715 };
2716
Ryan Sleevib8d7ea02018-05-07 20:01:012717 StaticSocketDataProvider data1(data_reads1, data_writes1);
2718 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592719 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2720 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2721
2722 TestCompletionCallback callback1;
2723
bnc691fda62016-08-12 00:43:162724 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202725 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592726
2727 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162728 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592729 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2730
Ryan Sleevib8d7ea02018-05-07 20:01:012731 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162732 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012733 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162734 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592735
bnc691fda62016-08-12 00:43:162736 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592737 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582738 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592739
2740 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162741 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592742 ASSERT_FALSE(endpoint.address().empty());
2743 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2744
2745 resolver->rules()->ClearRules();
2746 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2747
2748 TestCompletionCallback callback2;
2749
bnc691fda62016-08-12 00:43:162750 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592751 AuthCredentials(kFoo, kBar), callback2.callback())));
2752
2753 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162754 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592755 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2756 // The load timing after restart should have a new socket ID, and times after
2757 // those of the first load timing.
2758 EXPECT_LE(load_timing_info1.receive_headers_end,
2759 load_timing_info2.connect_timing.connect_start);
2760 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2761
Ryan Sleevib8d7ea02018-05-07 20:01:012762 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162763 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012764 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162765 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592766
bnc691fda62016-08-12 00:43:162767 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592768 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582769 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592770 EXPECT_EQ(100, response->headers->GetContentLength());
2771
bnc691fda62016-08-12 00:43:162772 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592773 ASSERT_FALSE(endpoint.address().empty());
2774 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2775}
2776
David Benjamin83ddfb32018-03-30 01:07:522777// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2778// will eventually give up.
2779TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2780 HttpRequestInfo request;
2781 request.method = "GET";
2782 request.url = GURL("http://www.example.org/");
2783 request.traffic_annotation =
2784 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2785
2786 TestNetLog log;
2787 session_deps_.net_log = &log;
2788 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2789 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2790
2791 MockWrite data_writes[] = {
2792 MockWrite("GET / HTTP/1.1\r\n"
2793 "Host: www.example.org\r\n"
2794 "Connection: keep-alive\r\n\r\n"),
2795 };
2796
2797 MockRead data_reads[] = {
2798 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2799 // Give a couple authenticate options (only the middle one is actually
2800 // supported).
2801 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2802 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2803 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2804 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2805 // Large content-length -- won't matter, as connection will be reset.
2806 MockRead("Content-Length: 10000\r\n\r\n"),
2807 MockRead(SYNCHRONOUS, ERR_FAILED),
2808 };
2809
2810 // After calling trans->RestartWithAuth(), this is the request we should
2811 // be issuing -- the final header line contains the credentials.
2812 MockWrite data_writes_restart[] = {
2813 MockWrite("GET / HTTP/1.1\r\n"
2814 "Host: www.example.org\r\n"
2815 "Connection: keep-alive\r\n"
2816 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2817 };
2818
Ryan Sleevib8d7ea02018-05-07 20:01:012819 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522820 session_deps_.socket_factory->AddSocketDataProvider(&data);
2821
2822 TestCompletionCallback callback;
2823 int rv = callback.GetResult(
2824 trans.Start(&request, callback.callback(), NetLogWithSource()));
2825
2826 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2827 for (int i = 0; i < 32; i++) {
2828 // Check the previous response was a 401.
2829 EXPECT_THAT(rv, IsOk());
2830 const HttpResponseInfo* response = trans.GetResponseInfo();
2831 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582832 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522833
2834 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012835 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522836 session_deps_.socket_factory->AddSocketDataProvider(
2837 data_restarts.back().get());
2838 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2839 callback.callback()));
2840 }
2841
2842 // After too many tries, the transaction should have given up.
2843 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2844}
2845
bncd16676a2016-07-20 16:23:012846TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462847 HttpRequestInfo request;
2848 request.method = "GET";
bncce36dca22015-04-21 22:11:232849 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292850 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:102851 request.traffic_annotation =
2852 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462853
danakj1fd259a02016-04-16 03:17:092854 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162855 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272856
[email protected]861fcd52009-08-26 02:33:462857 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232858 MockWrite(
2859 "GET / HTTP/1.1\r\n"
2860 "Host: www.example.org\r\n"
2861 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462862 };
2863
2864 MockRead data_reads[] = {
2865 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2866 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2868 // Large content-length -- won't matter, as connection will be reset.
2869 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062870 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462871 };
2872
Ryan Sleevib8d7ea02018-05-07 20:01:012873 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072874 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412875 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462876
tfarina42834112016-09-22 13:38:202877 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012878 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462879
2880 rv = callback.WaitForResult();
2881 EXPECT_EQ(0, rv);
2882
Ryan Sleevib8d7ea02018-05-07 20:01:012883 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162884 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012885 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162886 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192887
bnc691fda62016-08-12 00:43:162888 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522889 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582890 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462891}
2892
[email protected]2d2697f92009-02-18 21:00:322893// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2894// connection.
bncd16676a2016-07-20 16:23:012895TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182896 // On the second pass, the body read of the auth challenge is synchronous, so
2897 // IsConnectedAndIdle returns false. The socket should still be drained and
2898 // reused. See http://crbug.com/544255.
2899 for (int i = 0; i < 2; ++i) {
2900 HttpRequestInfo request;
2901 request.method = "GET";
2902 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102903 request.traffic_annotation =
2904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322905
mmenkecc2298e2015-12-07 18:20:182906 TestNetLog log;
2907 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092908 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272909
mmenkecc2298e2015-12-07 18:20:182910 MockWrite data_writes[] = {
2911 MockWrite(ASYNC, 0,
2912 "GET / HTTP/1.1\r\n"
2913 "Host: www.example.org\r\n"
2914 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322915
bnc691fda62016-08-12 00:43:162916 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182917 // be issuing -- the final header line contains the credentials.
2918 MockWrite(ASYNC, 6,
2919 "GET / HTTP/1.1\r\n"
2920 "Host: www.example.org\r\n"
2921 "Connection: keep-alive\r\n"
2922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2923 };
[email protected]2d2697f92009-02-18 21:00:322924
mmenkecc2298e2015-12-07 18:20:182925 MockRead data_reads[] = {
2926 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2927 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2928 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2929 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2930 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322931
mmenkecc2298e2015-12-07 18:20:182932 // Lastly, the server responds with the actual content.
2933 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2934 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2935 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2936 MockRead(ASYNC, 10, "Hello"),
2937 };
[email protected]2d2697f92009-02-18 21:00:322938
Ryan Sleevib8d7ea02018-05-07 20:01:012939 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182940 data.set_busy_before_sync_reads(true);
2941 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462942
mmenkecc2298e2015-12-07 18:20:182943 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322944
bnc691fda62016-08-12 00:43:162945 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202946 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012947 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322948
mmenkecc2298e2015-12-07 18:20:182949 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162950 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:182951 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322952
bnc691fda62016-08-12 00:43:162953 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182954 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582955 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:322956
mmenkecc2298e2015-12-07 18:20:182957 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252958
bnc691fda62016-08-12 00:43:162959 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2960 callback2.callback());
robpercival214763f2016-07-01 23:27:012961 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322962
mmenkecc2298e2015-12-07 18:20:182963 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162964 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:182965 TestLoadTimingReused(load_timing_info2);
2966 // The load timing after restart should have the same socket ID, and times
2967 // those of the first load timing.
2968 EXPECT_LE(load_timing_info1.receive_headers_end,
2969 load_timing_info2.send_start);
2970 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322971
bnc691fda62016-08-12 00:43:162972 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182973 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582974 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:182975 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322976
mmenkecc2298e2015-12-07 18:20:182977 std::string response_data;
bnc691fda62016-08-12 00:43:162978 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:322979
Ryan Sleevib8d7ea02018-05-07 20:01:012980 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162981 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012982 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162983 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:182984 }
[email protected]2d2697f92009-02-18 21:00:322985}
2986
2987// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2988// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:012989TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422990 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322991 request.method = "GET";
bncce36dca22015-04-21 22:11:232992 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102993 request.traffic_annotation =
2994 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322995
danakj1fd259a02016-04-16 03:17:092996 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272997
[email protected]2d2697f92009-02-18 21:00:322998 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:162999 MockWrite("GET / HTTP/1.1\r\n"
3000 "Host: www.example.org\r\n"
3001 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323002
bnc691fda62016-08-12 00:43:163003 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233004 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163005 MockWrite("GET / HTTP/1.1\r\n"
3006 "Host: www.example.org\r\n"
3007 "Connection: keep-alive\r\n"
3008 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323009 };
3010
[email protected]2d2697f92009-02-18 21:00:323011 MockRead data_reads1[] = {
3012 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3013 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313014 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323015
3016 // Lastly, the server responds with the actual content.
3017 MockRead("HTTP/1.1 200 OK\r\n"),
3018 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503019 MockRead("Content-Length: 5\r\n\r\n"),
3020 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323021 };
3022
[email protected]2d0a4f92011-05-05 16:38:463023 // An incorrect reconnect would cause this to be read.
3024 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063025 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463026 };
3027
Ryan Sleevib8d7ea02018-05-07 20:01:013028 StaticSocketDataProvider data1(data_reads1, data_writes1);
3029 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073030 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3031 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323032
[email protected]49639fa2011-12-20 23:22:413033 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323034
bnc691fda62016-08-12 00:43:163035 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203036 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323038
3039 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013040 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323041
bnc691fda62016-08-12 00:43:163042 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523043 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583044 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323045
[email protected]49639fa2011-12-20 23:22:413046 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323047
bnc691fda62016-08-12 00:43:163048 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013049 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323050
3051 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013052 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323053
bnc691fda62016-08-12 00:43:163054 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523055 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583056 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503057 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323058}
3059
3060// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3061// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013062TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423063 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323064 request.method = "GET";
bncce36dca22015-04-21 22:11:233065 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103066 request.traffic_annotation =
3067 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323068
danakj1fd259a02016-04-16 03:17:093069 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273070
[email protected]2d2697f92009-02-18 21:00:323071 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163072 MockWrite("GET / HTTP/1.1\r\n"
3073 "Host: www.example.org\r\n"
3074 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323075
bnc691fda62016-08-12 00:43:163076 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233077 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163078 MockWrite("GET / HTTP/1.1\r\n"
3079 "Host: www.example.org\r\n"
3080 "Connection: keep-alive\r\n"
3081 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323082 };
3083
3084 // Respond with 5 kb of response body.
3085 std::string large_body_string("Unauthorized");
3086 large_body_string.append(5 * 1024, ' ');
3087 large_body_string.append("\r\n");
3088
3089 MockRead data_reads1[] = {
3090 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3091 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3092 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3093 // 5134 = 12 + 5 * 1024 + 2
3094 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063095 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323096
3097 // Lastly, the server responds with the actual content.
3098 MockRead("HTTP/1.1 200 OK\r\n"),
3099 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503100 MockRead("Content-Length: 5\r\n\r\n"),
3101 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323102 };
3103
[email protected]2d0a4f92011-05-05 16:38:463104 // An incorrect reconnect would cause this to be read.
3105 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063106 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463107 };
3108
Ryan Sleevib8d7ea02018-05-07 20:01:013109 StaticSocketDataProvider data1(data_reads1, data_writes1);
3110 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073111 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3112 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323113
[email protected]49639fa2011-12-20 23:22:413114 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323115
bnc691fda62016-08-12 00:43:163116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203117 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323119
3120 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013121 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323122
bnc691fda62016-08-12 00:43:163123 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523124 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583125 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323126
[email protected]49639fa2011-12-20 23:22:413127 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323128
bnc691fda62016-08-12 00:43:163129 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013130 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323131
3132 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013133 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323134
bnc691fda62016-08-12 00:43:163135 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523136 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583137 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503138 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323139}
3140
3141// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313142// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013143TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313144 HttpRequestInfo request;
3145 request.method = "GET";
bncce36dca22015-04-21 22:11:233146 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103147 request.traffic_annotation =
3148 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313149
danakj1fd259a02016-04-16 03:17:093150 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273151
[email protected]11203f012009-11-12 23:02:313152 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233153 MockWrite(
3154 "GET / HTTP/1.1\r\n"
3155 "Host: www.example.org\r\n"
3156 "Connection: keep-alive\r\n\r\n"),
3157 // This simulates the seemingly successful write to a closed connection
3158 // if the bug is not fixed.
3159 MockWrite(
3160 "GET / HTTP/1.1\r\n"
3161 "Host: www.example.org\r\n"
3162 "Connection: keep-alive\r\n"
3163 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313164 };
3165
3166 MockRead data_reads1[] = {
3167 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3168 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3169 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3170 MockRead("Content-Length: 14\r\n\r\n"),
3171 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063172 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313173 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063174 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313175 };
3176
bnc691fda62016-08-12 00:43:163177 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313178 // be issuing -- the final header line contains the credentials.
3179 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233180 MockWrite(
3181 "GET / HTTP/1.1\r\n"
3182 "Host: www.example.org\r\n"
3183 "Connection: keep-alive\r\n"
3184 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313185 };
3186
3187 // Lastly, the server responds with the actual content.
3188 MockRead data_reads2[] = {
3189 MockRead("HTTP/1.1 200 OK\r\n"),
3190 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503191 MockRead("Content-Length: 5\r\n\r\n"),
3192 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313193 };
3194
Ryan Sleevib8d7ea02018-05-07 20:01:013195 StaticSocketDataProvider data1(data_reads1, data_writes1);
3196 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073197 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3198 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313199
[email protected]49639fa2011-12-20 23:22:413200 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313201
bnc691fda62016-08-12 00:43:163202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203203 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013204 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313205
3206 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013207 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313208
bnc691fda62016-08-12 00:43:163209 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523210 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583211 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313212
[email protected]49639fa2011-12-20 23:22:413213 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313214
bnc691fda62016-08-12 00:43:163215 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313217
3218 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013219 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313220
bnc691fda62016-08-12 00:43:163221 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523222 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583223 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503224 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313225}
3226
[email protected]394816e92010-08-03 07:38:593227// Test the request-challenge-retry sequence for basic auth, over a connection
3228// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013229TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013230 HttpRequestInfo request;
3231 request.method = "GET";
bncce36dca22015-04-21 22:11:233232 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013233 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293234 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103235 request.traffic_annotation =
3236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013237
3238 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593239 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493240 ProxyResolutionService::CreateFixedFromPacResult(
3241 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513242 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013243 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093244 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013245
3246 // Since we have proxy, should try to establish tunnel.
3247 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543248 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173249 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543250 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013251 };
3252
mmenkee71e15332015-10-07 16:39:543253 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013254 // connection.
3255 MockRead data_reads1[] = {
3256 // No credentials.
3257 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3258 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543259 };
ttuttle34f63b52015-03-05 04:33:013260
mmenkee71e15332015-10-07 16:39:543261 // Since the first connection couldn't be reused, need to establish another
3262 // once given credentials.
3263 MockWrite data_writes2[] = {
3264 // After calling trans->RestartWithAuth(), this is the request we should
3265 // be issuing -- the final header line contains the credentials.
3266 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173267 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543268 "Proxy-Connection: keep-alive\r\n"
3269 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3270
3271 MockWrite("GET / HTTP/1.1\r\n"
3272 "Host: www.example.org\r\n"
3273 "Connection: keep-alive\r\n\r\n"),
3274 };
3275
3276 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013277 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3278
3279 MockRead("HTTP/1.1 200 OK\r\n"),
3280 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3281 MockRead("Content-Length: 5\r\n\r\n"),
3282 MockRead(SYNCHRONOUS, "hello"),
3283 };
3284
Ryan Sleevib8d7ea02018-05-07 20:01:013285 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013286 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013287 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543288 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013289 SSLSocketDataProvider ssl(ASYNC, OK);
3290 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3291
3292 TestCompletionCallback callback1;
3293
bnc87dcefc2017-05-25 12:47:583294 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013296
3297 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013299
3300 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013301 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543302 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013303 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003304 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3305 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013306 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003307 entries, pos,
3308 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3309 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013310
3311 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523312 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013313 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523314 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013315 EXPECT_EQ(407, response->headers->response_code());
3316 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583317 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013318
3319 LoadTimingInfo load_timing_info;
3320 // CONNECT requests and responses are handled at the connect job level, so
3321 // the transaction does not yet have a connection.
3322 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3323
3324 TestCompletionCallback callback2;
3325
3326 rv =
3327 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013328 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013329
3330 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013331 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013332
3333 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523334 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013335
3336 EXPECT_TRUE(response->headers->IsKeepAlive());
3337 EXPECT_EQ(200, response->headers->response_code());
3338 EXPECT_EQ(5, response->headers->GetContentLength());
3339 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3340
3341 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583342 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013343
3344 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3345 TestLoadTimingNotReusedWithPac(load_timing_info,
3346 CONNECT_TIMING_HAS_SSL_TIMES);
3347
3348 trans.reset();
3349 session->CloseAllConnections();
3350}
3351
3352// Test the request-challenge-retry sequence for basic auth, over a connection
3353// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013354TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593355 HttpRequestInfo request;
3356 request.method = "GET";
bncce36dca22015-04-21 22:11:233357 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593358 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293359 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103360 request.traffic_annotation =
3361 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593362
[email protected]cb9bf6ca2011-01-28 13:15:273363 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593364 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493365 ProxyResolutionService::CreateFixedFromPacResult(
3366 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513367 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073368 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093369 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273370
[email protected]394816e92010-08-03 07:38:593371 // Since we have proxy, should try to establish tunnel.
3372 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543373 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173374 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543375 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113376 };
3377
mmenkee71e15332015-10-07 16:39:543378 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083379 // connection.
3380 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543381 // No credentials.
3382 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3383 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3384 MockRead("Proxy-Connection: close\r\n\r\n"),
3385 };
mmenkee0b5c882015-08-26 20:29:113386
mmenkee71e15332015-10-07 16:39:543387 MockWrite data_writes2[] = {
3388 // After calling trans->RestartWithAuth(), this is the request we should
3389 // be issuing -- the final header line contains the credentials.
3390 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173391 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543392 "Proxy-Connection: keep-alive\r\n"
3393 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083394
mmenkee71e15332015-10-07 16:39:543395 MockWrite("GET / HTTP/1.1\r\n"
3396 "Host: www.example.org\r\n"
3397 "Connection: keep-alive\r\n\r\n"),
3398 };
3399
3400 MockRead data_reads2[] = {
3401 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3402
3403 MockRead("HTTP/1.1 200 OK\r\n"),
3404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3405 MockRead("Content-Length: 5\r\n\r\n"),
3406 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593407 };
3408
Ryan Sleevib8d7ea02018-05-07 20:01:013409 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073410 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013411 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543412 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063413 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073414 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593415
[email protected]49639fa2011-12-20 23:22:413416 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593417
bnc87dcefc2017-05-25 12:47:583418 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193419 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503420
[email protected]49639fa2011-12-20 23:22:413421 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013422 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593423
3424 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013425 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543426 auto entries = log.GetEntries();
[email protected]394816e92010-08-03 07:38:593427 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003428 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3429 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593430 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403431 entries, pos,
mikecirone8b85c432016-09-08 19:11:003432 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3433 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593434
3435 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523436 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013437 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523438 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593439 EXPECT_EQ(407, response->headers->response_code());
3440 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583441 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593442
[email protected]029c83b62013-01-24 05:28:203443 LoadTimingInfo load_timing_info;
3444 // CONNECT requests and responses are handled at the connect job level, so
3445 // the transaction does not yet have a connection.
3446 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3447
[email protected]49639fa2011-12-20 23:22:413448 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593449
[email protected]49639fa2011-12-20 23:22:413450 rv = trans->RestartWithAuth(
3451 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013452 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593453
3454 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013455 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593456
3457 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523458 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593459
3460 EXPECT_TRUE(response->headers->IsKeepAlive());
3461 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503462 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593463 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3464
3465 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583466 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503467
[email protected]029c83b62013-01-24 05:28:203468 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3469 TestLoadTimingNotReusedWithPac(load_timing_info,
3470 CONNECT_TIMING_HAS_SSL_TIMES);
3471
[email protected]0b0bf032010-09-21 18:08:503472 trans.reset();
[email protected]102e27c2011-02-23 01:01:313473 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593474}
3475
[email protected]11203f012009-11-12 23:02:313476// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013477// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013478TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233479 // On the second pass, the body read of the auth challenge is synchronous, so
3480 // IsConnectedAndIdle returns false. The socket should still be drained and
3481 // reused. See http://crbug.com/544255.
3482 for (int i = 0; i < 2; ++i) {
3483 HttpRequestInfo request;
3484 request.method = "GET";
3485 request.url = GURL("https://www.example.org/");
3486 // Ensure that proxy authentication is attempted even
3487 // when the no authentication data flag is set.
3488 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103489 request.traffic_annotation =
3490 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013491
mmenked39192ee2015-12-09 00:57:233492 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593493 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493494 ProxyResolutionService::CreateFixed("myproxy:70",
3495 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233496 BoundTestNetLog log;
3497 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093498 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013499
bnc691fda62016-08-12 00:43:163500 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013501
mmenked39192ee2015-12-09 00:57:233502 // Since we have proxy, should try to establish tunnel.
3503 MockWrite data_writes1[] = {
3504 MockWrite(ASYNC, 0,
3505 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3506 "Host: www.example.org:443\r\n"
3507 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013508
bnc691fda62016-08-12 00:43:163509 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233510 // be issuing -- the final header line contains the credentials.
3511 MockWrite(ASYNC, 3,
3512 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3513 "Host: www.example.org:443\r\n"
3514 "Proxy-Connection: keep-alive\r\n"
3515 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3516 };
ttuttle34f63b52015-03-05 04:33:013517
mmenked39192ee2015-12-09 00:57:233518 // The proxy responds to the connect with a 407, using a persistent
3519 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3520 MockRead data_reads1[] = {
3521 // No credentials.
3522 MockRead(ASYNC, 1,
3523 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3524 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3525 "Proxy-Connection: keep-alive\r\n"
3526 "Content-Length: 10\r\n\r\n"),
3527 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013528
mmenked39192ee2015-12-09 00:57:233529 // Wrong credentials (wrong password).
3530 MockRead(ASYNC, 4,
3531 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3532 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3533 "Proxy-Connection: keep-alive\r\n"
3534 "Content-Length: 10\r\n\r\n"),
3535 // No response body because the test stops reading here.
3536 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3537 };
ttuttle34f63b52015-03-05 04:33:013538
Ryan Sleevib8d7ea02018-05-07 20:01:013539 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233540 data1.set_busy_before_sync_reads(true);
3541 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013542
mmenked39192ee2015-12-09 00:57:233543 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013544
bnc691fda62016-08-12 00:43:163545 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013546 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013547
Eric Roman79cc7552019-07-19 02:17:543548 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233549 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003550 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3551 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233552 ExpectLogContainsSomewhere(
3553 entries, pos,
mikecirone8b85c432016-09-08 19:11:003554 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3555 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013556
bnc691fda62016-08-12 00:43:163557 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233558 ASSERT_TRUE(response);
3559 ASSERT_TRUE(response->headers);
3560 EXPECT_TRUE(response->headers->IsKeepAlive());
3561 EXPECT_EQ(407, response->headers->response_code());
3562 EXPECT_EQ(10, response->headers->GetContentLength());
3563 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583564 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013565
mmenked39192ee2015-12-09 00:57:233566 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013567
mmenked39192ee2015-12-09 00:57:233568 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163569 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3570 callback2.callback());
robpercival214763f2016-07-01 23:27:013571 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013572
bnc691fda62016-08-12 00:43:163573 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233574 ASSERT_TRUE(response);
3575 ASSERT_TRUE(response->headers);
3576 EXPECT_TRUE(response->headers->IsKeepAlive());
3577 EXPECT_EQ(407, response->headers->response_code());
3578 EXPECT_EQ(10, response->headers->GetContentLength());
3579 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583580 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013581
mmenked39192ee2015-12-09 00:57:233582 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3583 // out of scope.
3584 session->CloseAllConnections();
3585 }
ttuttle34f63b52015-03-05 04:33:013586}
3587
3588// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3589// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013590TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233591 // On the second pass, the body read of the auth challenge is synchronous, so
3592 // IsConnectedAndIdle returns false. The socket should still be drained and
3593 // reused. See http://crbug.com/544255.
3594 for (int i = 0; i < 2; ++i) {
3595 HttpRequestInfo request;
3596 request.method = "GET";
3597 request.url = GURL("https://www.example.org/");
3598 // Ensure that proxy authentication is attempted even
3599 // when the no authentication data flag is set.
3600 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103601 request.traffic_annotation =
3602 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233603
3604 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593605 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493606 ProxyResolutionService::CreateFixed("myproxy:70",
3607 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233608 BoundTestNetLog log;
3609 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093610 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233611
bnc691fda62016-08-12 00:43:163612 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233613
3614 // Since we have proxy, should try to establish tunnel.
3615 MockWrite data_writes1[] = {
3616 MockWrite(ASYNC, 0,
3617 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3618 "Host: www.example.org:443\r\n"
3619 "Proxy-Connection: keep-alive\r\n\r\n"),
3620
bnc691fda62016-08-12 00:43:163621 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233622 // be issuing -- the final header line contains the credentials.
3623 MockWrite(ASYNC, 3,
3624 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3625 "Host: www.example.org:443\r\n"
3626 "Proxy-Connection: keep-alive\r\n"
3627 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3628 };
3629
3630 // The proxy responds to the connect with a 407, using a persistent
3631 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3632 MockRead data_reads1[] = {
3633 // No credentials.
3634 MockRead(ASYNC, 1,
3635 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3636 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3637 "Content-Length: 10\r\n\r\n"),
3638 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3639
3640 // Wrong credentials (wrong password).
3641 MockRead(ASYNC, 4,
3642 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3643 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3644 "Content-Length: 10\r\n\r\n"),
3645 // No response body because the test stops reading here.
3646 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3647 };
3648
Ryan Sleevib8d7ea02018-05-07 20:01:013649 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233650 data1.set_busy_before_sync_reads(true);
3651 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3652
3653 TestCompletionCallback callback1;
3654
bnc691fda62016-08-12 00:43:163655 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013656 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233657
Eric Roman79cc7552019-07-19 02:17:543658 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233659 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003660 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3661 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233662 ExpectLogContainsSomewhere(
3663 entries, pos,
mikecirone8b85c432016-09-08 19:11:003664 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3665 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233666
bnc691fda62016-08-12 00:43:163667 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233668 ASSERT_TRUE(response);
3669 ASSERT_TRUE(response->headers);
3670 EXPECT_TRUE(response->headers->IsKeepAlive());
3671 EXPECT_EQ(407, response->headers->response_code());
3672 EXPECT_EQ(10, response->headers->GetContentLength());
3673 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583674 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503675 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233676
3677 TestCompletionCallback callback2;
3678
3679 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163680 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3681 callback2.callback());
robpercival214763f2016-07-01 23:27:013682 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233683
bnc691fda62016-08-12 00:43:163684 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233685 ASSERT_TRUE(response);
3686 ASSERT_TRUE(response->headers);
3687 EXPECT_TRUE(response->headers->IsKeepAlive());
3688 EXPECT_EQ(407, response->headers->response_code());
3689 EXPECT_EQ(10, response->headers->GetContentLength());
3690 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583691 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503692 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233693
3694 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3695 // out of scope.
3696 session->CloseAllConnections();
3697 }
3698}
3699
3700// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3701// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3702// the case the server sends extra data on the original socket, so it can't be
3703// reused.
bncd16676a2016-07-20 16:23:013704TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273705 HttpRequestInfo request;
3706 request.method = "GET";
bncce36dca22015-04-21 22:11:233707 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273708 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293709 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103710 request.traffic_annotation =
3711 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273712
[email protected]2d2697f92009-02-18 21:00:323713 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593714 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493715 ProxyResolutionService::CreateFixedFromPacResult(
3716 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513717 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073718 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093719 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323720
[email protected]2d2697f92009-02-18 21:00:323721 // Since we have proxy, should try to establish tunnel.
3722 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233723 MockWrite(ASYNC, 0,
3724 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173725 "Host: www.example.org:443\r\n"
3726 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233727 };
[email protected]2d2697f92009-02-18 21:00:323728
mmenked39192ee2015-12-09 00:57:233729 // The proxy responds to the connect with a 407, using a persistent, but sends
3730 // extra data, so the socket cannot be reused.
3731 MockRead data_reads1[] = {
3732 // No credentials.
3733 MockRead(ASYNC, 1,
3734 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3735 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3736 "Content-Length: 10\r\n\r\n"),
3737 MockRead(SYNCHRONOUS, 2, "0123456789"),
3738 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3739 };
3740
3741 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233742 // After calling trans->RestartWithAuth(), this is the request we should
3743 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233744 MockWrite(ASYNC, 0,
3745 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173746 "Host: www.example.org:443\r\n"
3747 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233748 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3749
3750 MockWrite(ASYNC, 2,
3751 "GET / HTTP/1.1\r\n"
3752 "Host: www.example.org\r\n"
3753 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323754 };
3755
mmenked39192ee2015-12-09 00:57:233756 MockRead data_reads2[] = {
3757 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323758
mmenked39192ee2015-12-09 00:57:233759 MockRead(ASYNC, 3,
3760 "HTTP/1.1 200 OK\r\n"
3761 "Content-Type: text/html; charset=iso-8859-1\r\n"
3762 "Content-Length: 5\r\n\r\n"),
3763 // No response body because the test stops reading here.
3764 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323765 };
3766
Ryan Sleevib8d7ea02018-05-07 20:01:013767 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233768 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073769 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013770 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233771 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3772 SSLSocketDataProvider ssl(ASYNC, OK);
3773 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323774
[email protected]49639fa2011-12-20 23:22:413775 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323776
bnc87dcefc2017-05-25 12:47:583777 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193778 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323779
mmenked39192ee2015-12-09 00:57:233780 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013781 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233782
Eric Roman79cc7552019-07-19 02:17:543783 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393784 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003785 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3786 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393787 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403788 entries, pos,
mikecirone8b85c432016-09-08 19:11:003789 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3790 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323791
[email protected]1c773ea12009-04-28 19:58:423792 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243793 ASSERT_TRUE(response);
3794 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323795 EXPECT_TRUE(response->headers->IsKeepAlive());
3796 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423797 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583798 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323799
mmenked39192ee2015-12-09 00:57:233800 LoadTimingInfo load_timing_info;
3801 // CONNECT requests and responses are handled at the connect job level, so
3802 // the transaction does not yet have a connection.
3803 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3804
[email protected]49639fa2011-12-20 23:22:413805 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323806
mmenked39192ee2015-12-09 00:57:233807 rv =
3808 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013809 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323810
[email protected]2d2697f92009-02-18 21:00:323811 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233812 EXPECT_EQ(200, response->headers->response_code());
3813 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423814 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133815
mmenked39192ee2015-12-09 00:57:233816 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583817 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233818
3819 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3820 TestLoadTimingNotReusedWithPac(load_timing_info,
3821 CONNECT_TIMING_HAS_SSL_TIMES);
3822
3823 trans.reset();
[email protected]102e27c2011-02-23 01:01:313824 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323825}
3826
mmenkee71e15332015-10-07 16:39:543827// Test the case a proxy closes a socket while the challenge body is being
3828// drained.
bncd16676a2016-07-20 16:23:013829TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543830 HttpRequestInfo request;
3831 request.method = "GET";
3832 request.url = GURL("https://www.example.org/");
3833 // Ensure that proxy authentication is attempted even
3834 // when the no authentication data flag is set.
3835 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103836 request.traffic_annotation =
3837 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543838
3839 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493840 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3841 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093842 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543843
bnc691fda62016-08-12 00:43:163844 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543845
3846 // Since we have proxy, should try to establish tunnel.
3847 MockWrite data_writes1[] = {
3848 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173849 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543850 "Proxy-Connection: keep-alive\r\n\r\n"),
3851 };
3852
3853 // The proxy responds to the connect with a 407, using a persistent
3854 // connection.
3855 MockRead data_reads1[] = {
3856 // No credentials.
3857 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3858 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3859 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3860 // Server hands up in the middle of the body.
3861 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3862 };
3863
3864 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163865 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543866 // be issuing -- the final header line contains the credentials.
3867 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173868 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543869 "Proxy-Connection: keep-alive\r\n"
3870 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3871
3872 MockWrite("GET / HTTP/1.1\r\n"
3873 "Host: www.example.org\r\n"
3874 "Connection: keep-alive\r\n\r\n"),
3875 };
3876
3877 MockRead data_reads2[] = {
3878 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3879
3880 MockRead("HTTP/1.1 200 OK\r\n"),
3881 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3882 MockRead("Content-Length: 5\r\n\r\n"),
3883 MockRead(SYNCHRONOUS, "hello"),
3884 };
3885
Ryan Sleevib8d7ea02018-05-07 20:01:013886 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543887 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013888 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543889 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3890 SSLSocketDataProvider ssl(ASYNC, OK);
3891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3892
3893 TestCompletionCallback callback;
3894
tfarina42834112016-09-22 13:38:203895 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013896 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543897
bnc691fda62016-08-12 00:43:163898 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543899 ASSERT_TRUE(response);
3900 ASSERT_TRUE(response->headers);
3901 EXPECT_TRUE(response->headers->IsKeepAlive());
3902 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583903 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543904
bnc691fda62016-08-12 00:43:163905 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013906 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543907
bnc691fda62016-08-12 00:43:163908 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543909 ASSERT_TRUE(response);
3910 ASSERT_TRUE(response->headers);
3911 EXPECT_TRUE(response->headers->IsKeepAlive());
3912 EXPECT_EQ(200, response->headers->response_code());
3913 std::string body;
bnc691fda62016-08-12 00:43:163914 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543915 EXPECT_EQ("hello", body);
3916}
3917
[email protected]a8e9b162009-03-12 00:06:443918// Test that we don't read the response body when we fail to establish a tunnel,
3919// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013920TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273921 HttpRequestInfo request;
3922 request.method = "GET";
bncce36dca22015-04-21 22:11:233923 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103924 request.traffic_annotation =
3925 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273926
[email protected]a8e9b162009-03-12 00:06:443927 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493928 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3929 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443930
danakj1fd259a02016-04-16 03:17:093931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443932
bnc691fda62016-08-12 00:43:163933 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443934
[email protected]a8e9b162009-03-12 00:06:443935 // Since we have proxy, should try to establish tunnel.
3936 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173937 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3938 "Host: www.example.org:443\r\n"
3939 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443940 };
3941
3942 // The proxy responds to the connect with a 407.
3943 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243944 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3945 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3946 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233947 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243948 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443949 };
3950
Ryan Sleevib8d7ea02018-05-07 20:01:013951 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:073952 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443953
[email protected]49639fa2011-12-20 23:22:413954 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443955
tfarina42834112016-09-22 13:38:203956 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013957 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443958
3959 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013960 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:443961
bnc691fda62016-08-12 00:43:163962 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243963 ASSERT_TRUE(response);
3964 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443965 EXPECT_TRUE(response->headers->IsKeepAlive());
3966 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423967 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443968
3969 std::string response_data;
bnc691fda62016-08-12 00:43:163970 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:013971 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:183972
3973 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313974 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443975}
3976
ttuttle7933c112015-01-06 00:55:243977// Test that we don't pass extraneous headers from the proxy's response to the
3978// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:013979TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:243980 HttpRequestInfo request;
3981 request.method = "GET";
bncce36dca22015-04-21 22:11:233982 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103983 request.traffic_annotation =
3984 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:243985
3986 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493987 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3988 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:243989
danakj1fd259a02016-04-16 03:17:093990 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243991
bnc691fda62016-08-12 00:43:163992 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:243993
3994 // Since we have proxy, should try to establish tunnel.
3995 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173996 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3997 "Host: www.example.org:443\r\n"
3998 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243999 };
4000
4001 // The proxy responds to the connect with a 407.
4002 MockRead data_reads[] = {
4003 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4004 MockRead("X-Foo: bar\r\n"),
4005 MockRead("Set-Cookie: foo=bar\r\n"),
4006 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4007 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234008 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244009 };
4010
Ryan Sleevib8d7ea02018-05-07 20:01:014011 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244012 session_deps_.socket_factory->AddSocketDataProvider(&data);
4013
4014 TestCompletionCallback callback;
4015
tfarina42834112016-09-22 13:38:204016 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014017 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244018
4019 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014020 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244021
bnc691fda62016-08-12 00:43:164022 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244023 ASSERT_TRUE(response);
4024 ASSERT_TRUE(response->headers);
4025 EXPECT_TRUE(response->headers->IsKeepAlive());
4026 EXPECT_EQ(407, response->headers->response_code());
4027 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4028 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4029 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4030
4031 std::string response_data;
bnc691fda62016-08-12 00:43:164032 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014033 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244034
4035 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4036 session->CloseAllConnections();
4037}
4038
[email protected]8fdbcd22010-05-05 02:54:524039// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4040// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014041TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524042 HttpRequestInfo request;
4043 request.method = "GET";
bncce36dca22015-04-21 22:11:234044 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104045 request.traffic_annotation =
4046 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524047
[email protected]cb9bf6ca2011-01-28 13:15:274048 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094049 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164050 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274051
[email protected]8fdbcd22010-05-05 02:54:524052 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234053 MockWrite(
4054 "GET / HTTP/1.1\r\n"
4055 "Host: www.example.org\r\n"
4056 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524057 };
4058
4059 MockRead data_reads1[] = {
4060 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4061 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4062 // Large content-length -- won't matter, as connection will be reset.
4063 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064064 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524065 };
4066
Ryan Sleevib8d7ea02018-05-07 20:01:014067 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074068 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524069
[email protected]49639fa2011-12-20 23:22:414070 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524071
tfarina42834112016-09-22 13:38:204072 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014073 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524074
4075 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014076 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524077}
4078
[email protected]7a67a8152010-11-05 18:31:104079// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4080// through a non-authenticating proxy. The request should fail with
4081// ERR_UNEXPECTED_PROXY_AUTH.
4082// Note that it is impossible to detect if an HTTP server returns a 407 through
4083// a non-authenticating proxy - there is nothing to indicate whether the
4084// response came from the proxy or the server, so it is treated as if the proxy
4085// issued the challenge.
bncd16676a2016-07-20 16:23:014086TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274087 HttpRequestInfo request;
4088 request.method = "GET";
bncce36dca22015-04-21 22:11:234089 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104090 request.traffic_annotation =
4091 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274092
Ramin Halavatica8d5252018-03-12 05:33:494093 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4094 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514095 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074096 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094097 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104098
[email protected]7a67a8152010-11-05 18:31:104099 // Since we have proxy, should try to establish tunnel.
4100 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174101 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4102 "Host: www.example.org:443\r\n"
4103 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104104
rsleevidb16bb02015-11-12 23:47:174105 MockWrite("GET / HTTP/1.1\r\n"
4106 "Host: www.example.org\r\n"
4107 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104108 };
4109
4110 MockRead data_reads1[] = {
4111 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4112
4113 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4114 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4115 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064116 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104117 };
4118
Ryan Sleevib8d7ea02018-05-07 20:01:014119 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074120 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064121 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074122 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104123
[email protected]49639fa2011-12-20 23:22:414124 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104125
bnc691fda62016-08-12 00:43:164126 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104127
bnc691fda62016-08-12 00:43:164128 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014129 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104130
4131 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014132 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544133 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104134 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004135 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4136 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104137 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404138 entries, pos,
mikecirone8b85c432016-09-08 19:11:004139 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4140 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104141}
[email protected]2df19bb2010-08-25 20:13:464142
mmenke2a1781d2015-10-07 19:25:334143// Test a proxy auth scheme that allows default credentials and a proxy server
4144// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014145TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334146 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4147 HttpRequestInfo request;
4148 request.method = "GET";
4149 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104150 request.traffic_annotation =
4151 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334152
4153 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594154 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494155 ProxyResolutionService::CreateFixedFromPacResult(
4156 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334157
Jeremy Roman0579ed62017-08-29 15:56:194158 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334159 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194160 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334161 mock_handler->set_allows_default_credentials(true);
4162 auth_handler_factory->AddMockHandler(mock_handler.release(),
4163 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484164 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334165
4166 // Add NetLog just so can verify load timing information gets a NetLog ID.
4167 NetLog net_log;
4168 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094169 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334170
4171 // Since we have proxy, should try to establish tunnel.
4172 MockWrite data_writes1[] = {
4173 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174174 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334175 "Proxy-Connection: keep-alive\r\n\r\n"),
4176 };
4177
4178 // The proxy responds to the connect with a 407, using a non-persistent
4179 // connection.
4180 MockRead data_reads1[] = {
4181 // No credentials.
4182 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4183 MockRead("Proxy-Authenticate: Mock\r\n"),
4184 MockRead("Proxy-Connection: close\r\n\r\n"),
4185 };
4186
4187 // Since the first connection couldn't be reused, need to establish another
4188 // once given credentials.
4189 MockWrite data_writes2[] = {
4190 // After calling trans->RestartWithAuth(), this is the request we should
4191 // be issuing -- the final header line contains the credentials.
4192 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174193 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334194 "Proxy-Connection: keep-alive\r\n"
4195 "Proxy-Authorization: auth_token\r\n\r\n"),
4196
4197 MockWrite("GET / HTTP/1.1\r\n"
4198 "Host: www.example.org\r\n"
4199 "Connection: keep-alive\r\n\r\n"),
4200 };
4201
4202 MockRead data_reads2[] = {
4203 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4204
4205 MockRead("HTTP/1.1 200 OK\r\n"),
4206 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4207 MockRead("Content-Length: 5\r\n\r\n"),
4208 MockRead(SYNCHRONOUS, "hello"),
4209 };
4210
Ryan Sleevib8d7ea02018-05-07 20:01:014211 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334212 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014213 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334214 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4215 SSLSocketDataProvider ssl(ASYNC, OK);
4216 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4217
bnc87dcefc2017-05-25 12:47:584218 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194219 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334220
4221 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204222 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014223 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334224
4225 const HttpResponseInfo* response = trans->GetResponseInfo();
4226 ASSERT_TRUE(response);
4227 ASSERT_TRUE(response->headers);
4228 EXPECT_FALSE(response->headers->IsKeepAlive());
4229 EXPECT_EQ(407, response->headers->response_code());
4230 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4231 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584232 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334233
4234 LoadTimingInfo load_timing_info;
4235 // CONNECT requests and responses are handled at the connect job level, so
4236 // the transaction does not yet have a connection.
4237 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4238
4239 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014240 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334241 response = trans->GetResponseInfo();
4242 ASSERT_TRUE(response);
4243 ASSERT_TRUE(response->headers);
4244 EXPECT_TRUE(response->headers->IsKeepAlive());
4245 EXPECT_EQ(200, response->headers->response_code());
4246 EXPECT_EQ(5, response->headers->GetContentLength());
4247 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4248
4249 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584250 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334251
4252 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4253 TestLoadTimingNotReusedWithPac(load_timing_info,
4254 CONNECT_TIMING_HAS_SSL_TIMES);
4255
4256 trans.reset();
4257 session->CloseAllConnections();
4258}
4259
4260// Test a proxy auth scheme that allows default credentials and a proxy server
4261// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014262TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334263 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4264 HttpRequestInfo request;
4265 request.method = "GET";
4266 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104267 request.traffic_annotation =
4268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334269
4270 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594271 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494272 ProxyResolutionService::CreateFixedFromPacResult(
4273 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334274
Jeremy Roman0579ed62017-08-29 15:56:194275 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334276 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194277 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334278 mock_handler->set_allows_default_credentials(true);
4279 auth_handler_factory->AddMockHandler(mock_handler.release(),
4280 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484281 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334282
4283 // Add NetLog just so can verify load timing information gets a NetLog ID.
4284 NetLog net_log;
4285 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094286 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334287
4288 // Should try to establish tunnel.
4289 MockWrite data_writes1[] = {
4290 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174291 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334292 "Proxy-Connection: keep-alive\r\n\r\n"),
4293
4294 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174295 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334296 "Proxy-Connection: keep-alive\r\n"
4297 "Proxy-Authorization: auth_token\r\n\r\n"),
4298 };
4299
4300 // The proxy responds to the connect with a 407, using a non-persistent
4301 // connection.
4302 MockRead data_reads1[] = {
4303 // No credentials.
4304 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4305 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4306 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4307 };
4308
4309 // Since the first connection was closed, need to establish another once given
4310 // credentials.
4311 MockWrite data_writes2[] = {
4312 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174313 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334314 "Proxy-Connection: keep-alive\r\n"
4315 "Proxy-Authorization: auth_token\r\n\r\n"),
4316
4317 MockWrite("GET / HTTP/1.1\r\n"
4318 "Host: www.example.org\r\n"
4319 "Connection: keep-alive\r\n\r\n"),
4320 };
4321
4322 MockRead data_reads2[] = {
4323 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4324
4325 MockRead("HTTP/1.1 200 OK\r\n"),
4326 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4327 MockRead("Content-Length: 5\r\n\r\n"),
4328 MockRead(SYNCHRONOUS, "hello"),
4329 };
4330
Ryan Sleevib8d7ea02018-05-07 20:01:014331 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334332 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014333 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334334 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4335 SSLSocketDataProvider ssl(ASYNC, OK);
4336 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4337
bnc87dcefc2017-05-25 12:47:584338 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194339 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334340
4341 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204342 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014343 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334344
4345 const HttpResponseInfo* response = trans->GetResponseInfo();
4346 ASSERT_TRUE(response);
4347 ASSERT_TRUE(response->headers);
4348 EXPECT_TRUE(response->headers->IsKeepAlive());
4349 EXPECT_EQ(407, response->headers->response_code());
4350 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4351 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584352 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334353
4354 LoadTimingInfo load_timing_info;
4355 // CONNECT requests and responses are handled at the connect job level, so
4356 // the transaction does not yet have a connection.
4357 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4358
4359 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014360 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334361
4362 response = trans->GetResponseInfo();
4363 ASSERT_TRUE(response);
4364 ASSERT_TRUE(response->headers);
4365 EXPECT_TRUE(response->headers->IsKeepAlive());
4366 EXPECT_EQ(200, response->headers->response_code());
4367 EXPECT_EQ(5, response->headers->GetContentLength());
4368 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4369
4370 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584371 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334372
4373 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4374 TestLoadTimingNotReusedWithPac(load_timing_info,
4375 CONNECT_TIMING_HAS_SSL_TIMES);
4376
4377 trans.reset();
4378 session->CloseAllConnections();
4379}
4380
4381// Test a proxy auth scheme that allows default credentials and a proxy server
4382// that hangs up when credentials are initially sent, and hangs up again when
4383// they are retried.
bncd16676a2016-07-20 16:23:014384TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334385 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
4386 HttpRequestInfo request;
4387 request.method = "GET";
4388 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104389 request.traffic_annotation =
4390 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334391
4392 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594393 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494394 ProxyResolutionService::CreateFixedFromPacResult(
4395 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334396
Jeremy Roman0579ed62017-08-29 15:56:194397 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334398 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194399 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334400 mock_handler->set_allows_default_credentials(true);
4401 auth_handler_factory->AddMockHandler(mock_handler.release(),
4402 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484403 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334404
4405 // Add NetLog just so can verify load timing information gets a NetLog ID.
4406 NetLog net_log;
4407 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094408 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334409
4410 // Should try to establish tunnel.
4411 MockWrite data_writes1[] = {
4412 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174413 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334414 "Proxy-Connection: keep-alive\r\n\r\n"),
4415
4416 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174417 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334418 "Proxy-Connection: keep-alive\r\n"
4419 "Proxy-Authorization: auth_token\r\n\r\n"),
4420 };
4421
4422 // The proxy responds to the connect with a 407, and then hangs up after the
4423 // second request is sent.
4424 MockRead data_reads1[] = {
4425 // No credentials.
4426 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4427 MockRead("Content-Length: 0\r\n"),
4428 MockRead("Proxy-Connection: keep-alive\r\n"),
4429 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4430 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4431 };
4432
4433 // HttpNetworkTransaction sees a reused connection that was closed with
4434 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
4435 // request.
4436 MockWrite data_writes2[] = {
4437 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174438 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334439 "Proxy-Connection: keep-alive\r\n\r\n"),
4440 };
4441
4442 // The proxy, having had more than enough of us, just hangs up.
4443 MockRead data_reads2[] = {
4444 // No credentials.
4445 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4446 };
4447
Ryan Sleevib8d7ea02018-05-07 20:01:014448 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334449 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014450 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334451 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4452
bnc87dcefc2017-05-25 12:47:584453 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194454 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334455
4456 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204457 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014458 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334459
4460 const HttpResponseInfo* response = trans->GetResponseInfo();
4461 ASSERT_TRUE(response);
4462 ASSERT_TRUE(response->headers);
4463 EXPECT_TRUE(response->headers->IsKeepAlive());
4464 EXPECT_EQ(407, response->headers->response_code());
4465 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4466 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584467 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334468
4469 LoadTimingInfo load_timing_info;
4470 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4471
4472 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014473 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:334474
4475 trans.reset();
4476 session->CloseAllConnections();
4477}
4478
Asanka Herathbc3f8f62018-11-16 23:08:304479// This test exercises an odd edge case where the proxy closes the connection
4480// after the authentication handshake is complete. Presumably this technique is
4481// used in lieu of returning a 403 or 5xx status code when the authentication
4482// succeeds, but the user is not authorized to connect to the destination
4483// server. There's no standard for what a proxy should do to indicate a blocked
4484// site.
4485TEST_F(HttpNetworkTransactionTest,
4486 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
4487 HttpRequestInfo request;
4488 request.method = "GET";
4489 request.url = GURL("https://www.example.org/");
4490 request.traffic_annotation =
4491 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4492
4493 // Configure against proxy server "myproxy:70".
4494 session_deps_.proxy_resolution_service =
4495 ProxyResolutionService::CreateFixedFromPacResult(
4496 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4497
Asanka Herathbc3f8f62018-11-16 23:08:304498 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
4499 auth_handler_factory->set_do_init_from_challenge(true);
4500
4501 // Create two mock AuthHandlers. This is because the transaction gets retried
4502 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
4503 // was a real network error.
4504 //
4505 // The handlers support both default and explicit credentials. The retry
4506 // mentioned above should be able to reuse the default identity. Thus there
4507 // should never be a need to prompt for explicit credentials.
4508 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
4509 mock_handler->set_allows_default_credentials(true);
4510 mock_handler->set_allows_explicit_credentials(true);
4511 mock_handler->set_connection_based(true);
4512 auth_handler_factory->AddMockHandler(mock_handler.release(),
4513 HttpAuth::AUTH_PROXY);
4514 mock_handler = std::make_unique<HttpAuthHandlerMock>();
4515 mock_handler->set_allows_default_credentials(true);
4516 mock_handler->set_allows_explicit_credentials(true);
4517 mock_handler->set_connection_based(true);
4518 auth_handler_factory->AddMockHandler(mock_handler.release(),
4519 HttpAuth::AUTH_PROXY);
4520 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4521
4522 NetLog net_log;
4523 session_deps_.net_log = &net_log;
4524 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4525
4526 // Data for both sockets.
4527 //
4528 // Writes are for the tunnel establishment attempts and the
4529 // authentication handshake.
4530 MockWrite data_writes1[] = {
4531 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4532 "Host: www.example.org:443\r\n"
4533 "Proxy-Connection: keep-alive\r\n\r\n"),
4534
4535 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4536 "Host: www.example.org:443\r\n"
4537 "Proxy-Connection: keep-alive\r\n"
4538 "Proxy-Authorization: auth_token\r\n\r\n"),
4539
4540 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4541 "Host: www.example.org:443\r\n"
4542 "Proxy-Connection: keep-alive\r\n"
4543 "Proxy-Authorization: auth_token\r\n\r\n"),
4544 };
4545
4546 // The server side of the authentication handshake. Note that the response to
4547 // the final CONNECT request is ERR_CONNECTION_CLOSED.
4548 MockRead data_reads1[] = {
4549 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4550 MockRead("Content-Length: 0\r\n"),
4551 MockRead("Proxy-Connection: keep-alive\r\n"),
4552 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4553
4554 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4555 MockRead("Content-Length: 0\r\n"),
4556 MockRead("Proxy-Connection: keep-alive\r\n"),
4557 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
4558
4559 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4560 };
4561
4562 StaticSocketDataProvider data1(data_reads1, data_writes1);
4563 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4564
4565 // The second socket is for the reconnection attempt. Data is identical to the
4566 // first attempt.
4567 StaticSocketDataProvider data2(data_reads1, data_writes1);
4568 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4569
4570 auto trans =
4571 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4572
4573 TestCompletionCallback callback;
4574 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4575
4576 // Two rounds per handshake. After one retry, the error is propagated up the
4577 // stack.
4578 for (int i = 0; i < 4; ++i) {
4579 EXPECT_THAT(callback.GetResult(rv), IsOk());
4580
4581 const HttpResponseInfo* response = trans->GetResponseInfo();
4582 ASSERT_TRUE(response);
4583 ASSERT_TRUE(response->headers);
4584 EXPECT_EQ(407, response->headers->response_code());
4585 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
4586
4587 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4588 }
4589
4590 // One shall be the number thou shalt retry, and the number of the retrying
4591 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
4592 // that thou then proceed to one. Three is right out. Once the number one,
4593 // being the first number, be reached, then lobbest thou thy
4594 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
4595 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
4596
4597 trans.reset();
4598 session->CloseAllConnections();
4599}
4600
mmenke2a1781d2015-10-07 19:25:334601// Test a proxy auth scheme that allows default credentials and a proxy server
4602// that hangs up when credentials are initially sent, and sends a challenge
4603// again they are retried.
bncd16676a2016-07-20 16:23:014604TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334605 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
4606 HttpRequestInfo request;
4607 request.method = "GET";
4608 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104609 request.traffic_annotation =
4610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334611
4612 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594613 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494614 ProxyResolutionService::CreateFixedFromPacResult(
4615 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334616
Jeremy Roman0579ed62017-08-29 15:56:194617 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334618 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194619 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334620 mock_handler->set_allows_default_credentials(true);
4621 auth_handler_factory->AddMockHandler(mock_handler.release(),
4622 HttpAuth::AUTH_PROXY);
4623 // Add another handler for the second challenge. It supports default
4624 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194625 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334626 mock_handler->set_allows_default_credentials(true);
4627 auth_handler_factory->AddMockHandler(mock_handler.release(),
4628 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484629 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334630
4631 // Add NetLog just so can verify load timing information gets a NetLog ID.
4632 NetLog net_log;
4633 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094634 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334635
4636 // Should try to establish tunnel.
4637 MockWrite data_writes1[] = {
4638 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174639 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334640 "Proxy-Connection: keep-alive\r\n\r\n"),
4641 };
4642
4643 // The proxy responds to the connect with a 407, using a non-persistent
4644 // connection.
4645 MockRead data_reads1[] = {
4646 // No credentials.
4647 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4648 MockRead("Proxy-Authenticate: Mock\r\n"),
4649 MockRead("Proxy-Connection: close\r\n\r\n"),
4650 };
4651
4652 // Since the first connection was closed, need to establish another once given
4653 // credentials.
4654 MockWrite data_writes2[] = {
4655 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174656 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334657 "Proxy-Connection: keep-alive\r\n"
4658 "Proxy-Authorization: auth_token\r\n\r\n"),
4659 };
4660
4661 MockRead data_reads2[] = {
4662 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4663 MockRead("Proxy-Authenticate: Mock\r\n"),
4664 MockRead("Proxy-Connection: close\r\n\r\n"),
4665 };
4666
Ryan Sleevib8d7ea02018-05-07 20:01:014667 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334668 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014669 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334670 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4671 SSLSocketDataProvider ssl(ASYNC, OK);
4672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4673
bnc87dcefc2017-05-25 12:47:584674 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194675 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334676
4677 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204678 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014679 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334680
4681 const HttpResponseInfo* response = trans->GetResponseInfo();
4682 ASSERT_TRUE(response);
4683 ASSERT_TRUE(response->headers);
4684 EXPECT_EQ(407, response->headers->response_code());
4685 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4686 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584687 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334688
4689 LoadTimingInfo load_timing_info;
4690 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4691
4692 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014693 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334694 response = trans->GetResponseInfo();
4695 ASSERT_TRUE(response);
4696 ASSERT_TRUE(response->headers);
4697 EXPECT_EQ(407, response->headers->response_code());
4698 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584699 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334700
4701 trans.reset();
4702 session->CloseAllConnections();
4703}
4704
asankae2257db2016-10-11 22:03:164705// A more nuanced test than GenerateAuthToken test which asserts that
4706// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
4707// unnecessarily invalidated, and that if the server co-operates, the
4708// authentication handshake can continue with the same scheme but with a
4709// different identity.
4710TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
4711 HttpRequestInfo request;
4712 request.method = "GET";
4713 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104714 request.traffic_annotation =
4715 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:164716
Jeremy Roman0579ed62017-08-29 15:56:194717 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:164718 auth_handler_factory->set_do_init_from_challenge(true);
4719
4720 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:194721 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164722 mock_handler->set_allows_default_credentials(true);
4723 mock_handler->set_allows_explicit_credentials(true);
4724 mock_handler->set_connection_based(true);
4725 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
4726 auth_handler_factory->AddMockHandler(mock_handler.release(),
4727 HttpAuth::AUTH_SERVER);
4728
4729 // Add another handler for the second challenge. It supports default
4730 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194731 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164732 mock_handler->set_allows_default_credentials(true);
4733 mock_handler->set_allows_explicit_credentials(true);
4734 mock_handler->set_connection_based(true);
4735 auth_handler_factory->AddMockHandler(mock_handler.release(),
4736 HttpAuth::AUTH_SERVER);
4737 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4738
4739 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4740
4741 MockWrite data_writes1[] = {
4742 MockWrite("GET / HTTP/1.1\r\n"
4743 "Host: www.example.org\r\n"
4744 "Connection: keep-alive\r\n\r\n"),
4745 };
4746
4747 MockRead data_reads1[] = {
4748 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4749 "WWW-Authenticate: Mock\r\n"
4750 "Connection: keep-alive\r\n\r\n"),
4751 };
4752
4753 // Identical to data_writes1[]. The AuthHandler encounters a
4754 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
4755 // transaction procceds without an authorization header.
4756 MockWrite data_writes2[] = {
4757 MockWrite("GET / HTTP/1.1\r\n"
4758 "Host: www.example.org\r\n"
4759 "Connection: keep-alive\r\n\r\n"),
4760 };
4761
4762 MockRead data_reads2[] = {
4763 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4764 "WWW-Authenticate: Mock\r\n"
4765 "Connection: keep-alive\r\n\r\n"),
4766 };
4767
4768 MockWrite data_writes3[] = {
4769 MockWrite("GET / HTTP/1.1\r\n"
4770 "Host: www.example.org\r\n"
4771 "Connection: keep-alive\r\n"
4772 "Authorization: auth_token\r\n\r\n"),
4773 };
4774
4775 MockRead data_reads3[] = {
4776 MockRead("HTTP/1.1 200 OK\r\n"
4777 "Content-Length: 5\r\n"
4778 "Content-Type: text/plain\r\n"
4779 "Connection: keep-alive\r\n\r\n"
4780 "Hello"),
4781 };
4782
Ryan Sleevib8d7ea02018-05-07 20:01:014783 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:164784 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4785
Ryan Sleevib8d7ea02018-05-07 20:01:014786 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:164787 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4788
Ryan Sleevib8d7ea02018-05-07 20:01:014789 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:164790 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4791
bnc87dcefc2017-05-25 12:47:584792 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194793 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:164794
4795 TestCompletionCallback callback;
4796 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4797 EXPECT_THAT(callback.GetResult(rv), IsOk());
4798
4799 const HttpResponseInfo* response = trans->GetResponseInfo();
4800 ASSERT_TRUE(response);
4801 ASSERT_TRUE(response->headers);
4802 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4803
4804 // The following three tests assert that an authentication challenge was
4805 // received and that the stack is ready to respond to the challenge using
4806 // ambient credentials.
4807 EXPECT_EQ(401, response->headers->response_code());
4808 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584809 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164810
4811 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4812 EXPECT_THAT(callback.GetResult(rv), IsOk());
4813 response = trans->GetResponseInfo();
4814 ASSERT_TRUE(response);
4815 ASSERT_TRUE(response->headers);
4816
4817 // The following three tests assert that an authentication challenge was
4818 // received and that the stack needs explicit credentials before it is ready
4819 // to respond to the challenge.
4820 EXPECT_EQ(401, response->headers->response_code());
4821 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584822 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164823
4824 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4825 EXPECT_THAT(callback.GetResult(rv), IsOk());
4826 response = trans->GetResponseInfo();
4827 ASSERT_TRUE(response);
4828 ASSERT_TRUE(response->headers);
4829 EXPECT_EQ(200, response->headers->response_code());
4830
4831 trans.reset();
4832 session->CloseAllConnections();
4833}
4834
Matt Menked1eb6d42018-01-17 04:54:064835// Proxy resolver that returns a proxy with the same host and port for different
4836// schemes, based on the path of the URL being requests.
4837class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
4838 public:
4839 SameProxyWithDifferentSchemesProxyResolver() {}
4840 ~SameProxyWithDifferentSchemesProxyResolver() override {}
4841
4842 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
4843
4844 static HostPortPair ProxyHostPortPair() {
4845 return HostPortPair::FromString(ProxyHostPortPairAsString());
4846 }
4847
4848 // ProxyResolver implementation.
4849 int GetProxyForURL(const GURL& url,
4850 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:174851 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:064852 std::unique_ptr<Request>* request,
4853 const NetLogWithSource& /*net_log*/) override {
4854 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:574855 results->set_traffic_annotation(
4856 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:064857 if (url.path() == "/socks4") {
4858 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
4859 return OK;
4860 }
4861 if (url.path() == "/socks5") {
4862 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
4863 return OK;
4864 }
4865 if (url.path() == "/http") {
4866 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
4867 return OK;
4868 }
4869 if (url.path() == "/https") {
4870 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
4871 return OK;
4872 }
Matt Menkee8648fa2019-01-17 16:47:074873 if (url.path() == "/https_trusted") {
4874 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
4875 ProxyHostPortPair(),
4876 true /* is_trusted_proxy */));
4877 return OK;
4878 }
Matt Menked1eb6d42018-01-17 04:54:064879 NOTREACHED();
4880 return ERR_NOT_IMPLEMENTED;
4881 }
4882
4883 private:
4884 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
4885};
4886
4887class SameProxyWithDifferentSchemesProxyResolverFactory
4888 : public ProxyResolverFactory {
4889 public:
4890 SameProxyWithDifferentSchemesProxyResolverFactory()
4891 : ProxyResolverFactory(false) {}
4892
Lily Houghton99597862018-03-07 16:40:424893 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
4894 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:174895 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:424896 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:064897 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
4898 return OK;
4899 }
4900
4901 private:
4902 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
4903};
4904
4905// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:074906// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:064907// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
4908// request to foo.com using proxy.com as an HTTP proxy.
4909TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:494910 session_deps_.proxy_resolution_service =
4911 std::make_unique<ProxyResolutionService>(
4912 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
4913 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
4914 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
4915 nullptr);
Matt Menked1eb6d42018-01-17 04:54:064916
4917 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4918
4919 MockWrite socks_writes[] = {
4920 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
4921 kSOCKS4OkRequestLocalHostPort80Length),
4922 MockWrite(SYNCHRONOUS,
4923 "GET /socks4 HTTP/1.1\r\n"
4924 "Host: test\r\n"
4925 "Connection: keep-alive\r\n\r\n"),
4926 };
4927 MockRead socks_reads[] = {
4928 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
4929 MockRead("HTTP/1.0 200 OK\r\n"
4930 "Connection: keep-alive\r\n"
4931 "Content-Length: 15\r\n\r\n"
4932 "SOCKS4 Response"),
4933 };
Ryan Sleevib8d7ea02018-05-07 20:01:014934 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:064935 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
4936
4937 const char kSOCKS5Request[] = {
4938 0x05, // Version
4939 0x01, // Command (CONNECT)
4940 0x00, // Reserved
4941 0x03, // Address type (DOMAINNAME)
4942 0x04, // Length of domain (4)
4943 't', 'e', 's', 't', // Domain string
4944 0x00, 0x50, // 16-bit port (80)
4945 };
4946 MockWrite socks5_writes[] = {
4947 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:244948 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:064949 MockWrite(SYNCHRONOUS,
4950 "GET /socks5 HTTP/1.1\r\n"
4951 "Host: test\r\n"
4952 "Connection: keep-alive\r\n\r\n"),
4953 };
4954 MockRead socks5_reads[] = {
4955 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
4956 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
4957 MockRead("HTTP/1.0 200 OK\r\n"
4958 "Connection: keep-alive\r\n"
4959 "Content-Length: 15\r\n\r\n"
4960 "SOCKS5 Response"),
4961 };
Ryan Sleevib8d7ea02018-05-07 20:01:014962 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:064963 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
4964
4965 MockWrite http_writes[] = {
4966 MockWrite(SYNCHRONOUS,
4967 "GET http://test/http HTTP/1.1\r\n"
4968 "Host: test\r\n"
4969 "Proxy-Connection: keep-alive\r\n\r\n"),
4970 };
4971 MockRead http_reads[] = {
4972 MockRead("HTTP/1.1 200 OK\r\n"
4973 "Proxy-Connection: keep-alive\r\n"
4974 "Content-Length: 13\r\n\r\n"
4975 "HTTP Response"),
4976 };
Ryan Sleevib8d7ea02018-05-07 20:01:014977 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:064978 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
4979
4980 MockWrite https_writes[] = {
4981 MockWrite(SYNCHRONOUS,
4982 "GET http://test/https HTTP/1.1\r\n"
4983 "Host: test\r\n"
4984 "Proxy-Connection: keep-alive\r\n\r\n"),
4985 };
4986 MockRead https_reads[] = {
4987 MockRead("HTTP/1.1 200 OK\r\n"
4988 "Proxy-Connection: keep-alive\r\n"
4989 "Content-Length: 14\r\n\r\n"
4990 "HTTPS Response"),
4991 };
Ryan Sleevib8d7ea02018-05-07 20:01:014992 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:064993 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
4994 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
4995 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4996
Matt Menkee8648fa2019-01-17 16:47:074997 MockWrite https_trusted_writes[] = {
4998 MockWrite(SYNCHRONOUS,
4999 "GET http://test/https_trusted HTTP/1.1\r\n"
5000 "Host: test\r\n"
5001 "Proxy-Connection: keep-alive\r\n\r\n"),
5002 };
5003 MockRead https_trusted_reads[] = {
5004 MockRead("HTTP/1.1 200 OK\r\n"
5005 "Proxy-Connection: keep-alive\r\n"
5006 "Content-Length: 22\r\n\r\n"
5007 "HTTPS Trusted Response"),
5008 };
5009 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5010 https_trusted_writes);
5011 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5012 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5013 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5014
Matt Menked1eb6d42018-01-17 04:54:065015 struct TestCase {
5016 GURL url;
5017 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075018 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065019 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075020 int expected_idle_socks4_sockets;
5021 int expected_idle_socks5_sockets;
5022 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5023 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065024 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075025 int expected_idle_https_sockets;
5026 // How many idle sockets there should be in the HTTPS proxy socket pool with
5027 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5028 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065029 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075030 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5031 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5032 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5033 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5034 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5035 1},
Matt Menked1eb6d42018-01-17 04:54:065036 };
5037
5038 for (const auto& test_case : kTestCases) {
5039 HttpRequestInfo request;
5040 request.method = "GET";
5041 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105042 request.traffic_annotation =
5043 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065044 std::unique_ptr<HttpNetworkTransaction> trans =
5045 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5046 session.get());
5047 TestCompletionCallback callback;
5048 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5049 EXPECT_THAT(callback.GetResult(rv), IsOk());
5050
5051 const HttpResponseInfo* response = trans->GetResponseInfo();
5052 ASSERT_TRUE(response);
5053 ASSERT_TRUE(response->headers);
5054 EXPECT_EQ(200, response->headers->response_code());
5055 std::string response_data;
5056 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5057 EXPECT_EQ(test_case.expected_response, response_data);
5058
5059 // Return the socket to the socket pool, so can make sure it's not used for
5060 // the next requests.
5061 trans.reset();
5062 base::RunLoop().RunUntilIdle();
5063
5064 // Check the number of idle sockets in the pool, to make sure that used
5065 // sockets are indeed being returned to the socket pool. If each request
5066 // doesn't return an idle socket to the pool, the test would incorrectly
5067 // pass.
Matt Menkee8648fa2019-01-17 16:47:075068 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5069 session
Matt Menked23ab952019-03-06 00:24:405070 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075071 HttpNetworkSession::NORMAL_SOCKET_POOL,
5072 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5073 SameProxyWithDifferentSchemesProxyResolver::
5074 ProxyHostPortPair()))
5075 ->IdleSocketCount());
5076 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5077 session
Matt Menked23ab952019-03-06 00:24:405078 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075079 HttpNetworkSession::NORMAL_SOCKET_POOL,
5080 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5081 SameProxyWithDifferentSchemesProxyResolver::
5082 ProxyHostPortPair()))
5083 ->IdleSocketCount());
5084 EXPECT_EQ(test_case.expected_idle_http_sockets,
5085 session
Matt Menked23ab952019-03-06 00:24:405086 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075087 HttpNetworkSession::NORMAL_SOCKET_POOL,
5088 ProxyServer(ProxyServer::SCHEME_HTTP,
5089 SameProxyWithDifferentSchemesProxyResolver::
5090 ProxyHostPortPair()))
5091 ->IdleSocketCount());
5092 EXPECT_EQ(test_case.expected_idle_https_sockets,
5093 session
Matt Menked23ab952019-03-06 00:24:405094 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075095 HttpNetworkSession::NORMAL_SOCKET_POOL,
5096 ProxyServer(ProxyServer::SCHEME_HTTPS,
5097 SameProxyWithDifferentSchemesProxyResolver::
5098 ProxyHostPortPair()))
5099 ->IdleSocketCount());
5100 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5101 session
Matt Menked23ab952019-03-06 00:24:405102 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075103 HttpNetworkSession::NORMAL_SOCKET_POOL,
5104 ProxyServer(ProxyServer::SCHEME_HTTPS,
5105 SameProxyWithDifferentSchemesProxyResolver::
5106 ProxyHostPortPair(),
5107 true /* is_trusted_proxy */))
5108 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065109 }
5110}
5111
[email protected]029c83b62013-01-24 05:28:205112// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015113TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205114 HttpRequestInfo request1;
5115 request1.method = "GET";
bncce36dca22015-04-21 22:11:235116 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105117 request1.traffic_annotation =
5118 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205119
5120 HttpRequestInfo request2;
5121 request2.method = "GET";
bncce36dca22015-04-21 22:11:235122 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105123 request2.traffic_annotation =
5124 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205125
5126 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495127 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5128 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515129 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075130 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095131 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205132
5133 // Since we have proxy, should try to establish tunnel.
5134 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175135 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5136 "Host: www.example.org:443\r\n"
5137 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205138
rsleevidb16bb02015-11-12 23:47:175139 MockWrite("GET /1 HTTP/1.1\r\n"
5140 "Host: www.example.org\r\n"
5141 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205142
rsleevidb16bb02015-11-12 23:47:175143 MockWrite("GET /2 HTTP/1.1\r\n"
5144 "Host: www.example.org\r\n"
5145 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205146 };
5147
5148 // The proxy responds to the connect with a 407, using a persistent
5149 // connection.
5150 MockRead data_reads1[] = {
5151 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5152
5153 MockRead("HTTP/1.1 200 OK\r\n"),
5154 MockRead("Content-Length: 1\r\n\r\n"),
5155 MockRead(SYNCHRONOUS, "1"),
5156
5157 MockRead("HTTP/1.1 200 OK\r\n"),
5158 MockRead("Content-Length: 2\r\n\r\n"),
5159 MockRead(SYNCHRONOUS, "22"),
5160 };
5161
Ryan Sleevib8d7ea02018-05-07 20:01:015162 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075163 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205164 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075165 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205166
5167 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585168 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195169 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205170
5171 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015172 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205173
5174 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015175 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205176
5177 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525178 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475179 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525180 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205181 EXPECT_EQ(1, response1->headers->GetContentLength());
5182
5183 LoadTimingInfo load_timing_info1;
5184 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5185 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5186
5187 trans1.reset();
5188
5189 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585190 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195191 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205192
5193 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205195
5196 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015197 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205198
5199 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525200 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475201 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525202 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205203 EXPECT_EQ(2, response2->headers->GetContentLength());
5204
5205 LoadTimingInfo load_timing_info2;
5206 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5207 TestLoadTimingReused(load_timing_info2);
5208
5209 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5210
5211 trans2.reset();
5212 session->CloseAllConnections();
5213}
5214
5215// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015216TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205217 HttpRequestInfo request1;
5218 request1.method = "GET";
bncce36dca22015-04-21 22:11:235219 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105220 request1.traffic_annotation =
5221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205222
5223 HttpRequestInfo request2;
5224 request2.method = "GET";
bncce36dca22015-04-21 22:11:235225 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105226 request2.traffic_annotation =
5227 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205228
5229 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595230 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495231 ProxyResolutionService::CreateFixedFromPacResult(
5232 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515233 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075234 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095235 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205236
5237 // Since we have proxy, should try to establish tunnel.
5238 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175239 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5240 "Host: www.example.org:443\r\n"
5241 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205242
rsleevidb16bb02015-11-12 23:47:175243 MockWrite("GET /1 HTTP/1.1\r\n"
5244 "Host: www.example.org\r\n"
5245 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205246
rsleevidb16bb02015-11-12 23:47:175247 MockWrite("GET /2 HTTP/1.1\r\n"
5248 "Host: www.example.org\r\n"
5249 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205250 };
5251
5252 // The proxy responds to the connect with a 407, using a persistent
5253 // connection.
5254 MockRead data_reads1[] = {
5255 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5256
5257 MockRead("HTTP/1.1 200 OK\r\n"),
5258 MockRead("Content-Length: 1\r\n\r\n"),
5259 MockRead(SYNCHRONOUS, "1"),
5260
5261 MockRead("HTTP/1.1 200 OK\r\n"),
5262 MockRead("Content-Length: 2\r\n\r\n"),
5263 MockRead(SYNCHRONOUS, "22"),
5264 };
5265
Ryan Sleevib8d7ea02018-05-07 20:01:015266 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075267 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205268 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205270
5271 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585272 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195273 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205274
5275 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205277
5278 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015279 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205280
5281 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525282 ASSERT_TRUE(response1);
5283 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205284 EXPECT_EQ(1, response1->headers->GetContentLength());
5285
5286 LoadTimingInfo load_timing_info1;
5287 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5288 TestLoadTimingNotReusedWithPac(load_timing_info1,
5289 CONNECT_TIMING_HAS_SSL_TIMES);
5290
5291 trans1.reset();
5292
5293 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585294 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205296
5297 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205299
5300 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015301 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205302
5303 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525304 ASSERT_TRUE(response2);
5305 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205306 EXPECT_EQ(2, response2->headers->GetContentLength());
5307
5308 LoadTimingInfo load_timing_info2;
5309 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5310 TestLoadTimingReusedWithPac(load_timing_info2);
5311
5312 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5313
5314 trans2.reset();
5315 session->CloseAllConnections();
5316}
5317
[email protected]2df19bb2010-08-25 20:13:465318// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015319TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275320 HttpRequestInfo request;
5321 request.method = "GET";
bncce36dca22015-04-21 22:11:235322 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105323 request.traffic_annotation =
5324 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275325
[email protected]2df19bb2010-08-25 20:13:465326 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495327 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5328 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515329 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075330 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095331 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:465332
[email protected]2df19bb2010-08-25 20:13:465333 // Since we have proxy, should use full url
5334 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235335 MockWrite(
5336 "GET http://www.example.org/ HTTP/1.1\r\n"
5337 "Host: www.example.org\r\n"
5338 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465339 };
5340
5341 MockRead data_reads1[] = {
5342 MockRead("HTTP/1.1 200 OK\r\n"),
5343 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5344 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065345 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465346 };
5347
Ryan Sleevib8d7ea02018-05-07 20:01:015348 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075349 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065350 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075351 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465352
[email protected]49639fa2011-12-20 23:22:415353 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465354
bnc691fda62016-08-12 00:43:165355 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505356
bnc691fda62016-08-12 00:43:165357 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465359
5360 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015361 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465362
[email protected]58e32bb2013-01-21 18:23:255363 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165364 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255365 TestLoadTimingNotReused(load_timing_info,
5366 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5367
bnc691fda62016-08-12 00:43:165368 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525369 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465370
tbansal2ecbbc72016-10-06 17:15:475371 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:465372 EXPECT_TRUE(response->headers->IsKeepAlive());
5373 EXPECT_EQ(200, response->headers->response_code());
5374 EXPECT_EQ(100, response->headers->GetContentLength());
5375 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5376
5377 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585378 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:465379}
5380
[email protected]7642b5ae2010-09-01 20:55:175381// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015382TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275383 HttpRequestInfo request;
5384 request.method = "GET";
bncce36dca22015-04-21 22:11:235385 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105386 request.traffic_annotation =
5387 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275388
[email protected]7642b5ae2010-09-01 20:55:175389 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495390 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5391 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515392 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075393 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095394 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:175395
bncce36dca22015-04-21 22:11:235396 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135397 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455398 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415399 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:175400
Ryan Hamilton0239aac2018-05-19 00:03:135401 spdy::SpdySerializedFrame resp(
5402 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5403 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:175404 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415405 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:175406 };
5407
Ryan Sleevib8d7ea02018-05-07 20:01:015408 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075409 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:175410
[email protected]8ddf8322012-02-23 18:08:065411 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365412 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:175414
[email protected]49639fa2011-12-20 23:22:415415 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:175416
bnc691fda62016-08-12 00:43:165417 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505418
bnc691fda62016-08-12 00:43:165419 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015420 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:175421
5422 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015423 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:175424
[email protected]58e32bb2013-01-21 18:23:255425 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165426 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255427 TestLoadTimingNotReused(load_timing_info,
5428 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5429
bnc691fda62016-08-12 00:43:165430 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525431 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:475432 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:525433 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025434 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:175435
5436 std::string response_data;
bnc691fda62016-08-12 00:43:165437 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235438 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:175439}
5440
[email protected]1c173852014-06-19 12:51:505441// Verifies that a session which races and wins against the owning transaction
5442// (completing prior to host resolution), doesn't fail the transaction.
5443// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:015444TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:505445 HttpRequestInfo request;
5446 request.method = "GET";
bncce36dca22015-04-21 22:11:235447 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105448 request.traffic_annotation =
5449 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:505450
5451 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495452 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5453 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515454 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:505455 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095456 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:505457
bncce36dca22015-04-21 22:11:235458 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:135459 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455460 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415461 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:505462
Raul Tambre94493c652019-03-11 17:18:355463 spdy::SpdySerializedFrame resp(
5464 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135465 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:505466 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415467 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:505468 };
5469
Ryan Sleevib8d7ea02018-05-07 20:01:015470 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:505471 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5472
5473 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365474 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:505475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5476
5477 TestCompletionCallback callback1;
5478
bnc691fda62016-08-12 00:43:165479 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:505480
5481 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:505482 session_deps_.host_resolver->set_ondemand_mode(true);
5483
bnc691fda62016-08-12 00:43:165484 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015485 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:505486
5487 // Race a session to the proxy, which completes first.
5488 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:045489 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115490 PRIVACY_MODE_DISABLED,
5491 SpdySessionKey::IsProxySession::kTrue, SocketTag());
[email protected]1c173852014-06-19 12:51:505492 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:525493 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:505494
5495 // Unstall the resolution begun by the transaction.
5496 session_deps_.host_resolver->set_ondemand_mode(true);
5497 session_deps_.host_resolver->ResolveAllPending();
5498
5499 EXPECT_FALSE(callback1.have_result());
5500 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015501 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:505502
bnc691fda62016-08-12 00:43:165503 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525504 ASSERT_TRUE(response);
5505 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025506 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:505507
5508 std::string response_data;
bnc691fda62016-08-12 00:43:165509 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:505510 EXPECT_EQ(kUploadData, response_data);
5511}
5512
[email protected]dc7bd1c52010-11-12 00:01:135513// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015514TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:275515 HttpRequestInfo request;
5516 request.method = "GET";
bncce36dca22015-04-21 22:11:235517 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105518 request.traffic_annotation =
5519 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275520
[email protected]79cb5c12011-09-12 13:12:045521 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495522 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5523 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515524 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075525 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095526 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:135527
[email protected]dc7bd1c52010-11-12 00:01:135528 // The first request will be a bare GET, the second request will be a
5529 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:455530 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:135531 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485532 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385533 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:135534 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465535 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:135536 };
Ryan Hamilton0239aac2018-05-19 00:03:135537 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245538 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485539 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:135540 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415541 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:135542 };
5543
5544 // The first response is a 407 proxy authentication challenge, and the second
5545 // response will be a 200 response since the second request includes a valid
5546 // Authorization header.
5547 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465548 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:135549 };
Ryan Hamilton0239aac2018-05-19 00:03:135550 spdy::SpdySerializedFrame resp_authentication(
5551 spdy_util_.ConstructSpdyReplyError(
5552 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245553 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135554 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415555 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135556 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:355557 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135558 spdy::SpdySerializedFrame body_data(
5559 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:135560 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415561 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465562 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415563 CreateMockRead(resp_data, 4),
5564 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:135565 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:135566 };
5567
Ryan Sleevib8d7ea02018-05-07 20:01:015568 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075569 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:135570
[email protected]8ddf8322012-02-23 18:08:065571 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365572 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075573 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:135574
[email protected]49639fa2011-12-20 23:22:415575 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:135576
bnc691fda62016-08-12 00:43:165577 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:135578
bnc691fda62016-08-12 00:43:165579 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015580 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135581
5582 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015583 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135584
bnc691fda62016-08-12 00:43:165585 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135586
wezca1070932016-05-26 20:30:525587 ASSERT_TRUE(response);
5588 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:135589 EXPECT_EQ(407, response->headers->response_code());
5590 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585591 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:135592
[email protected]49639fa2011-12-20 23:22:415593 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:135594
bnc691fda62016-08-12 00:43:165595 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015596 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135597
5598 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015599 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135600
bnc691fda62016-08-12 00:43:165601 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135602
wezca1070932016-05-26 20:30:525603 ASSERT_TRUE(response_restart);
5604 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:135605 EXPECT_EQ(200, response_restart->headers->response_code());
5606 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585607 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:135608}
5609
[email protected]d9da5fe2010-10-13 22:37:165610// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:015611TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:275612 HttpRequestInfo request;
5613 request.method = "GET";
bncce36dca22015-04-21 22:11:235614 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105615 request.traffic_annotation =
5616 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275617
[email protected]d9da5fe2010-10-13 22:37:165618 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495619 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5620 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515621 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075622 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095623 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165624
bnc691fda62016-08-12 00:43:165625 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165626
bncce36dca22015-04-21 22:11:235627 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135628 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045629 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5630 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235631 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:165632
bncce36dca22015-04-21 22:11:235633 const char get[] =
5634 "GET / HTTP/1.1\r\n"
5635 "Host: www.example.org\r\n"
5636 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135637 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:195638 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:135639 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355640 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:165641 const char resp[] = "HTTP/1.1 200 OK\r\n"
5642 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135643 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:195644 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:135645 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:195646 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:135647 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:415648 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:045649
5650 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415651 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5652 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:045653 };
5654
[email protected]d9da5fe2010-10-13 22:37:165655 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415656 CreateMockRead(conn_resp, 1, ASYNC),
5657 CreateMockRead(wrapped_get_resp, 3, ASYNC),
5658 CreateMockRead(wrapped_body, 4, ASYNC),
5659 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135660 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:165661 };
5662
Ryan Sleevib8d7ea02018-05-07 20:01:015663 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075664 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165665
[email protected]8ddf8322012-02-23 18:08:065666 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365667 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075668 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065669 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075670 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165671
[email protected]49639fa2011-12-20 23:22:415672 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165673
bnc691fda62016-08-12 00:43:165674 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015675 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165676
5677 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015678 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165679
[email protected]58e32bb2013-01-21 18:23:255680 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165681 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255682 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5683
bnc691fda62016-08-12 00:43:165684 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525685 ASSERT_TRUE(response);
5686 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:165687 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5688
5689 std::string response_data;
bnc691fda62016-08-12 00:43:165690 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:165691 EXPECT_EQ("1234567890", response_data);
5692}
5693
5694// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:015695TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
5696 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:385697
[email protected]cb9bf6ca2011-01-28 13:15:275698 HttpRequestInfo request;
5699 request.method = "GET";
bncce36dca22015-04-21 22:11:235700 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105701 request.traffic_annotation =
5702 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275703
[email protected]d9da5fe2010-10-13 22:37:165704 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495705 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5706 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515707 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075708 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095709 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165710
bnc691fda62016-08-12 00:43:165711 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165712
bncce36dca22015-04-21 22:11:235713 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135714 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045715 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5716 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235717 // fetch https://www.example.org/ via SPDY
5718 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:135719 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:495720 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135721 spdy::SpdySerializedFrame wrapped_get(
5722 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
5723 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355724 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135725 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355726 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135727 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:025728 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135729 spdy::SpdySerializedFrame body(
5730 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
5731 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:025732 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135733 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:415734 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:135735 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:415736 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:045737
5738 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415739 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5740 CreateMockWrite(window_update_get_resp, 6),
5741 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:045742 };
5743
[email protected]d9da5fe2010-10-13 22:37:165744 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415745 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:095746 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:415747 CreateMockRead(wrapped_get_resp, 4, ASYNC),
5748 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135749 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:165750 };
5751
Ryan Sleevib8d7ea02018-05-07 20:01:015752 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075753 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165754
[email protected]8ddf8322012-02-23 18:08:065755 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365756 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075757 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065758 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365759 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165761
[email protected]49639fa2011-12-20 23:22:415762 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165763
bnc691fda62016-08-12 00:43:165764 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015765 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165766
rch32320842015-05-16 15:57:095767 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:555768 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:095769 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:595770 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:165771 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015772 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165773
[email protected]58e32bb2013-01-21 18:23:255774 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165775 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255776 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5777
bnc691fda62016-08-12 00:43:165778 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525779 ASSERT_TRUE(response);
5780 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025781 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:165782
5783 std::string response_data;
bnc691fda62016-08-12 00:43:165784 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235785 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:165786}
5787
5788// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015789TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:275790 HttpRequestInfo request;
5791 request.method = "GET";
bncce36dca22015-04-21 22:11:235792 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105793 request.traffic_annotation =
5794 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275795
[email protected]d9da5fe2010-10-13 22:37:165796 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495797 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5798 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515799 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075800 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095801 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165802
bnc691fda62016-08-12 00:43:165803 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165804
bncce36dca22015-04-21 22:11:235805 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135806 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045807 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5808 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:135809 spdy::SpdySerializedFrame get(
5810 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:165811
5812 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415813 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:165814 };
5815
Ryan Hamilton0239aac2018-05-19 00:03:135816 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
5817 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:165818 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415819 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:165820 };
5821
Ryan Sleevib8d7ea02018-05-07 20:01:015822 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075823 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165824
[email protected]8ddf8322012-02-23 18:08:065825 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365826 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075827 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065828 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365829 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075830 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165831
[email protected]49639fa2011-12-20 23:22:415832 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165833
bnc691fda62016-08-12 00:43:165834 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015835 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165836
5837 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015838 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:165839
ttuttle960fcbf2016-04-19 13:26:325840 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:165841}
5842
Matt Menkecb2cd0982018-12-19 17:54:045843// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:245844// is observed, but does exist by the time auth credentials are provided. In
5845// this case, auth and SSL are fully negotated on the second request, but then
5846// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:045847TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
5848 ProxyConfig proxy_config;
5849 proxy_config.set_auto_detect(true);
5850 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
5851
5852 CapturingProxyResolver capturing_proxy_resolver;
5853 capturing_proxy_resolver.set_proxy_server(
5854 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
5855 session_deps_.proxy_resolution_service =
5856 std::make_unique<ProxyResolutionService>(
5857 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5858 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
5859 std::make_unique<CapturingProxyResolverFactory>(
5860 &capturing_proxy_resolver),
5861 nullptr);
5862
5863 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5864
5865 const char kMyUrl[] = "https://www.example.org/";
5866 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
5867 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355868 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:045869 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5870
5871 spdy_util_.UpdateWithStreamDestruction(1);
5872 spdy::SpdySerializedFrame get2(
5873 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
5874 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:355875 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:045876 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
5877
5878 MockWrite auth_challenge_writes[] = {
5879 MockWrite(ASYNC, 0,
5880 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5881 "Host: www.example.org:443\r\n"
5882 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:245883 MockWrite(ASYNC, 2,
5884 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5885 "Host: www.example.org:443\r\n"
5886 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:045887 };
5888
5889 MockRead auth_challenge_reads[] = {
5890 MockRead(ASYNC, 1,
5891 "HTTP/1.1 407 Authentication Required\r\n"
5892 "Content-Length: 0\r\n"
5893 "Proxy-Connection: close\r\n"
5894 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
5895 };
5896
5897 MockWrite spdy_writes[] = {
5898 MockWrite(ASYNC, 0,
5899 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5900 "Host: www.example.org:443\r\n"
5901 "Proxy-Connection: keep-alive\r\n"
5902 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5903 CreateMockWrite(get, 2),
5904 CreateMockWrite(get2, 5),
5905 };
5906
5907 MockRead spdy_reads[] = {
5908 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5909 CreateMockRead(get_resp, 3, ASYNC),
5910 CreateMockRead(body, 4, ASYNC),
5911 CreateMockRead(get_resp2, 6, ASYNC),
5912 CreateMockRead(body2, 7, ASYNC),
5913
5914 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
5915 };
5916
Matt Menke5062be22019-05-01 17:50:245917 MockWrite auth_response_writes_discarded_socket[] = {
5918 MockWrite(ASYNC, 0,
5919 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5920 "Host: www.example.org:443\r\n"
5921 "Proxy-Connection: keep-alive\r\n"
5922 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5923 };
5924
5925 MockRead auth_response_reads_discarded_socket[] = {
5926 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5927 };
5928
Matt Menkecb2cd0982018-12-19 17:54:045929 SequencedSocketData auth_challenge1(auth_challenge_reads,
5930 auth_challenge_writes);
5931 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
5932
5933 SequencedSocketData auth_challenge2(auth_challenge_reads,
5934 auth_challenge_writes);
5935 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
5936
5937 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
5938 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5939
Matt Menke5062be22019-05-01 17:50:245940 SequencedSocketData auth_response_discarded_socket(
5941 auth_response_reads_discarded_socket,
5942 auth_response_writes_discarded_socket);
5943 session_deps_.socket_factory->AddSocketDataProvider(
5944 &auth_response_discarded_socket);
5945
Matt Menkecb2cd0982018-12-19 17:54:045946 SSLSocketDataProvider ssl(ASYNC, OK);
5947 ssl.next_proto = kProtoHTTP2;
5948 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5949
Matt Menke5062be22019-05-01 17:50:245950 SSLSocketDataProvider ssl2(ASYNC, OK);
5951 ssl2.next_proto = kProtoHTTP2;
5952 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5953
Matt Menkecb2cd0982018-12-19 17:54:045954 TestCompletionCallback callback;
5955 std::string response_data;
5956
5957 // Run first request until an auth challenge is observed.
5958 HttpRequestInfo request1;
5959 request1.method = "GET";
5960 request1.url = GURL(kMyUrl);
5961 request1.traffic_annotation =
5962 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5963 HttpNetworkTransaction trans1(LOWEST, session.get());
5964 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
5965 EXPECT_THAT(callback.GetResult(rv), IsOk());
5966 const HttpResponseInfo* response = trans1.GetResponseInfo();
5967 ASSERT_TRUE(response);
5968 ASSERT_TRUE(response->headers);
5969 EXPECT_EQ(407, response->headers->response_code());
5970 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:585971 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:045972
5973 // Run second request until an auth challenge is observed.
5974 HttpRequestInfo request2;
5975 request2.method = "GET";
5976 request2.url = GURL(kMyUrl);
5977 request2.traffic_annotation =
5978 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5979 HttpNetworkTransaction trans2(LOWEST, session.get());
5980 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
5981 EXPECT_THAT(callback.GetResult(rv), IsOk());
5982 response = trans2.GetResponseInfo();
5983 ASSERT_TRUE(response);
5984 ASSERT_TRUE(response->headers);
5985 EXPECT_EQ(407, response->headers->response_code());
5986 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:585987 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:045988
5989 // Now provide credentials for the first request, and wait for it to complete.
5990 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
5991 rv = callback.GetResult(rv);
5992 EXPECT_THAT(rv, IsOk());
5993 response = trans1.GetResponseInfo();
5994 ASSERT_TRUE(response);
5995 ASSERT_TRUE(response->headers);
5996 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
5997 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
5998 EXPECT_EQ(kUploadData, response_data);
5999
6000 // Now provide credentials for the second request. It should notice the
6001 // existing session, and reuse it.
6002 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6003 EXPECT_THAT(callback.GetResult(rv), IsOk());
6004 response = trans2.GetResponseInfo();
6005 ASSERT_TRUE(response);
6006 ASSERT_TRUE(response->headers);
6007 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6008 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6009 EXPECT_EQ(kUploadData, response_data);
6010}
6011
[email protected]f6c63db52013-02-02 00:35:226012// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6013// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016014TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226015 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6016 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496017 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6018 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516019 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076020 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096021 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506022 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226023
6024 HttpRequestInfo request1;
6025 request1.method = "GET";
bncce36dca22015-04-21 22:11:236026 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226027 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106028 request1.traffic_annotation =
6029 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226030
6031 HttpRequestInfo request2;
6032 request2.method = "GET";
bncce36dca22015-04-21 22:11:236033 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226034 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106035 request2.traffic_annotation =
6036 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226037
bncce36dca22015-04-21 22:11:236038 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136039 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046040 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6041 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136042 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356043 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226044
bncce36dca22015-04-21 22:11:236045 // Fetch https://www.example.org/ via HTTP.
6046 const char get1[] =
6047 "GET / HTTP/1.1\r\n"
6048 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226049 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136050 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196051 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226052 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6053 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136054 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196055 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136056 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196057 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136058 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416059 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226060
bncce36dca22015-04-21 22:11:236061 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136062 spdy::SpdyHeaderBlock connect2_block;
6063 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6064 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6065 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046066 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6067 false));
[email protected]601e03f12014-04-06 16:26:396068
Ryan Hamilton0239aac2018-05-19 00:03:136069 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356070 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226071
bncce36dca22015-04-21 22:11:236072 // Fetch https://mail.example.org/ via HTTP.
6073 const char get2[] =
6074 "GET / HTTP/1.1\r\n"
6075 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226076 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136077 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196078 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226079 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6080 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136081 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196082 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136083 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196084 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226085
6086 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416087 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6088 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226089 };
6090
6091 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416092 CreateMockRead(conn_resp1, 1, ASYNC),
6093 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6094 CreateMockRead(wrapped_body1, 4, ASYNC),
6095 CreateMockRead(conn_resp2, 6, ASYNC),
6096 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6097 CreateMockRead(wrapped_body2, 9, ASYNC),
6098 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226099 };
6100
Ryan Sleevib8d7ea02018-05-07 20:01:016101 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506102 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226103
6104 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366105 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506106 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226107 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506108 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226109 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506110 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226111
6112 TestCompletionCallback callback;
6113
bnc691fda62016-08-12 00:43:166114 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206115 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016116 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226117
6118 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166119 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226120 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6121
bnc691fda62016-08-12 00:43:166122 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526123 ASSERT_TRUE(response);
6124 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226125 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6126
6127 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446128 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166129 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506130 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226131
bnc691fda62016-08-12 00:43:166132 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206133 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016134 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226135
6136 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166137 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226138 // Even though the SPDY connection is reused, a new tunnelled connection has
6139 // to be created, so the socket's load timing looks like a fresh connection.
6140 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6141
6142 // The requests should have different IDs, since they each are using their own
6143 // separate stream.
6144 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6145
bnc691fda62016-08-12 00:43:166146 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506147 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226148}
6149
6150// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6151// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016152TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226153 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6154 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496155 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6156 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516157 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076158 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096159 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506160 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226161
6162 HttpRequestInfo request1;
6163 request1.method = "GET";
bncce36dca22015-04-21 22:11:236164 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226165 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106166 request1.traffic_annotation =
6167 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226168
6169 HttpRequestInfo request2;
6170 request2.method = "GET";
bncce36dca22015-04-21 22:11:236171 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226172 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106173 request2.traffic_annotation =
6174 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226175
bncce36dca22015-04-21 22:11:236176 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136177 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046178 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6179 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136180 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356181 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226182
bncce36dca22015-04-21 22:11:236183 // Fetch https://www.example.org/ via HTTP.
6184 const char get1[] =
6185 "GET / HTTP/1.1\r\n"
6186 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226187 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136188 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196189 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226190 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6191 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136192 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196193 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136194 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196195 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136196 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416197 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226198
bncce36dca22015-04-21 22:11:236199 // Fetch https://www.example.org/2 via HTTP.
6200 const char get2[] =
6201 "GET /2 HTTP/1.1\r\n"
6202 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226203 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136204 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196205 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226206 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6207 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136208 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196209 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136210 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196211 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226212
6213 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416214 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6215 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226216 };
6217
6218 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416219 CreateMockRead(conn_resp1, 1, ASYNC),
6220 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466221 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416222 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466223 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416224 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226225 };
6226
Ryan Sleevib8d7ea02018-05-07 20:01:016227 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506228 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226229
6230 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366231 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226233 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506234 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226235
6236 TestCompletionCallback callback;
6237
bnc87dcefc2017-05-25 12:47:586238 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196239 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206240 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016241 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226242
6243 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016244 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226245
6246 LoadTimingInfo load_timing_info;
6247 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6248 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6249
6250 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526251 ASSERT_TRUE(response);
6252 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226253 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6254
6255 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446256 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506257 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226258 trans.reset();
6259
bnc87dcefc2017-05-25 12:47:586260 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196261 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206262 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016263 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226264
[email protected]f6c63db52013-02-02 00:35:226265 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016266 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226267
6268 LoadTimingInfo load_timing_info2;
6269 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6270 TestLoadTimingReused(load_timing_info2);
6271
6272 // The requests should have the same ID.
6273 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6274
[email protected]90499482013-06-01 00:39:506275 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226276}
6277
6278// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6279// Proxy to different servers.
bncd16676a2016-07-20 16:23:016280TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226281 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496282 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6283 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516284 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076285 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096286 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506287 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226288
6289 HttpRequestInfo request1;
6290 request1.method = "GET";
bncce36dca22015-04-21 22:11:236291 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226292 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106293 request1.traffic_annotation =
6294 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226295
6296 HttpRequestInfo request2;
6297 request2.method = "GET";
bncce36dca22015-04-21 22:11:236298 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226299 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106300 request2.traffic_annotation =
6301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226302
bncce36dca22015-04-21 22:11:236303 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136304 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236305 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136306 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156307 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136308 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356309 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136310 spdy::SpdySerializedFrame body1(
6311 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386312 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226313
bncce36dca22015-04-21 22:11:236314 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136315 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236316 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136317 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156318 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136319 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356320 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136321 spdy::SpdySerializedFrame body2(
6322 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:226323
6324 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416325 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:226326 };
6327
6328 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416329 CreateMockRead(get_resp1, 1, ASYNC),
6330 CreateMockRead(body1, 2, ASYNC),
6331 CreateMockRead(get_resp2, 4, ASYNC),
6332 CreateMockRead(body2, 5, ASYNC),
6333 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:226334 };
6335
Ryan Sleevib8d7ea02018-05-07 20:01:016336 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506337 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226338
6339 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366340 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506341 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226342
6343 TestCompletionCallback callback;
6344
bnc87dcefc2017-05-25 12:47:586345 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196346 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206347 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016348 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226349
6350 LoadTimingInfo load_timing_info;
6351 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6352 TestLoadTimingNotReused(load_timing_info,
6353 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6354
6355 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526356 ASSERT_TRUE(response);
6357 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026358 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:226359
6360 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446361 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:506362 rv = trans->Read(buf.get(), 256, callback.callback());
6363 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226364 // Delete the first request, so the second one can reuse the socket.
6365 trans.reset();
6366
bnc691fda62016-08-12 00:43:166367 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206368 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016369 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226370
6371 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166372 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226373 TestLoadTimingReused(load_timing_info2);
6374
6375 // The requests should have the same ID.
6376 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6377
bnc691fda62016-08-12 00:43:166378 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506379 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226380}
6381
Matt Menke2436b2f2018-12-11 18:07:116382// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
6383// direct (non-proxied) request to the proxy server are not pooled, as that
6384// would break socket pool isolation.
6385TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
6386 ProxyConfig proxy_config;
6387 proxy_config.set_auto_detect(true);
6388 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6389
6390 CapturingProxyResolver capturing_proxy_resolver;
6391 session_deps_.proxy_resolution_service =
6392 std::make_unique<ProxyResolutionService>(
6393 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6394 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6395 std::make_unique<CapturingProxyResolverFactory>(
6396 &capturing_proxy_resolver),
6397 nullptr);
6398
6399 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6400
6401 SpdyTestUtil spdy_util1;
6402 // CONNECT to www.example.org:443 via HTTP/2.
6403 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046404 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6405 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116406 // fetch https://www.example.org/ via HTTP/2.
6407 const char kMyUrl[] = "https://www.example.org/";
6408 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6409 spdy::SpdySerializedFrame wrapped_get(
6410 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6411 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356412 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116413 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356414 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116415 spdy::SpdySerializedFrame wrapped_get_resp(
6416 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6417 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
6418 spdy::SpdySerializedFrame wrapped_body(
6419 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6420 spdy::SpdySerializedFrame window_update_get_resp(
6421 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6422 spdy::SpdySerializedFrame window_update_body(
6423 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6424
6425 MockWrite spdy_writes1[] = {
6426 CreateMockWrite(connect, 0),
6427 CreateMockWrite(wrapped_get, 2),
6428 CreateMockWrite(window_update_get_resp, 6),
6429 CreateMockWrite(window_update_body, 7),
6430 };
6431
6432 MockRead spdy_reads1[] = {
6433 CreateMockRead(conn_resp, 1, ASYNC),
6434 MockRead(ASYNC, ERR_IO_PENDING, 3),
6435 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6436 CreateMockRead(wrapped_body, 5, ASYNC),
6437 MockRead(ASYNC, 0, 8),
6438 };
6439
6440 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6441 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6442
6443 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
6444 // a new pipe.
6445 SpdyTestUtil spdy_util2;
6446 spdy::SpdySerializedFrame req(
6447 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6448 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
6449
6450 spdy::SpdySerializedFrame resp(
6451 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6452 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
6453 MockRead spdy_reads2[] = {
6454 CreateMockRead(resp, 1),
6455 CreateMockRead(data, 2),
6456 MockRead(ASYNC, 0, 3),
6457 };
6458 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6459 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6460
6461 SSLSocketDataProvider ssl(ASYNC, OK);
6462 ssl.next_proto = kProtoHTTP2;
6463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6464 SSLSocketDataProvider ssl2(ASYNC, OK);
6465 ssl2.next_proto = kProtoHTTP2;
6466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6467 SSLSocketDataProvider ssl3(ASYNC, OK);
6468 ssl3.next_proto = kProtoHTTP2;
6469 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6470
6471 TestCompletionCallback callback;
6472 std::string response_data;
6473
6474 // Make a request using proxy:70 as a HTTP/2 proxy.
6475 capturing_proxy_resolver.set_proxy_server(
6476 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6477 HttpRequestInfo request1;
6478 request1.method = "GET";
6479 request1.url = GURL("https://www.example.org/");
6480 request1.traffic_annotation =
6481 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6482
6483 HttpNetworkTransaction trans1(LOWEST, session.get());
6484 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6485 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6486
6487 // Allow the SpdyProxyClientSocket's write callback to complete.
6488 base::RunLoop().RunUntilIdle();
6489 // Now allow the read of the response to complete.
6490 spdy_data1.Resume();
6491 rv = callback.WaitForResult();
6492 EXPECT_THAT(rv, IsOk());
6493
6494 const HttpResponseInfo* response = trans1.GetResponseInfo();
6495 ASSERT_TRUE(response);
6496 ASSERT_TRUE(response->headers);
6497 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6498
6499 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6500 EXPECT_EQ(kUploadData, response_data);
6501 RunUntilIdle();
6502
6503 // Make a direct HTTP/2 request to proxy:70.
6504 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6505 HttpRequestInfo request2;
6506 request2.method = "GET";
6507 request2.url = GURL("https://proxy:70/");
6508 request2.traffic_annotation =
6509 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6510 HttpNetworkTransaction trans2(LOWEST, session.get());
6511 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
6512 NetLogWithSource())),
6513 IsOk());
6514 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6515}
6516
6517// Same as above, but reverse request order, since the code to check for an
6518// existing session is different for tunnels and direct connections.
6519TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
6520 // Configure against https proxy server "myproxy:80".
6521 ProxyConfig proxy_config;
6522 proxy_config.set_auto_detect(true);
6523 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6524
6525 CapturingProxyResolver capturing_proxy_resolver;
6526 session_deps_.proxy_resolution_service =
6527 std::make_unique<ProxyResolutionService>(
6528 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6529 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6530 std::make_unique<CapturingProxyResolverFactory>(
6531 &capturing_proxy_resolver),
6532 nullptr);
6533
6534 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6535 // Fetch https://proxy:70/ via HTTP/2.
6536 SpdyTestUtil spdy_util1;
6537 spdy::SpdySerializedFrame req(
6538 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6539 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
6540
6541 spdy::SpdySerializedFrame resp(
6542 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
6543 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
6544 MockRead spdy_reads1[] = {
6545 CreateMockRead(resp, 1),
6546 CreateMockRead(data, 2),
6547 MockRead(ASYNC, 0, 3),
6548 };
6549 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6550 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6551
6552 SpdyTestUtil spdy_util2;
6553 // CONNECT to www.example.org:443 via HTTP/2.
6554 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046555 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6556 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116557 // fetch https://www.example.org/ via HTTP/2.
6558 const char kMyUrl[] = "https://www.example.org/";
6559 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6560 spdy::SpdySerializedFrame wrapped_get(
6561 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6562 spdy::SpdySerializedFrame conn_resp(
6563 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6564 spdy::SpdySerializedFrame get_resp(
6565 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6566 spdy::SpdySerializedFrame wrapped_get_resp(
6567 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6568 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
6569 spdy::SpdySerializedFrame wrapped_body(
6570 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6571 spdy::SpdySerializedFrame window_update_get_resp(
6572 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6573 spdy::SpdySerializedFrame window_update_body(
6574 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6575
6576 MockWrite spdy_writes2[] = {
6577 CreateMockWrite(connect, 0),
6578 CreateMockWrite(wrapped_get, 2),
6579 CreateMockWrite(window_update_get_resp, 6),
6580 CreateMockWrite(window_update_body, 7),
6581 };
6582
6583 MockRead spdy_reads2[] = {
6584 CreateMockRead(conn_resp, 1, ASYNC),
6585 MockRead(ASYNC, ERR_IO_PENDING, 3),
6586 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6587 CreateMockRead(wrapped_body, 5, ASYNC),
6588 MockRead(ASYNC, 0, 8),
6589 };
6590
6591 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6592 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6593
6594 SSLSocketDataProvider ssl(ASYNC, OK);
6595 ssl.next_proto = kProtoHTTP2;
6596 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6597 SSLSocketDataProvider ssl2(ASYNC, OK);
6598 ssl2.next_proto = kProtoHTTP2;
6599 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6600 SSLSocketDataProvider ssl3(ASYNC, OK);
6601 ssl3.next_proto = kProtoHTTP2;
6602 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6603
6604 TestCompletionCallback callback;
6605 std::string response_data;
6606
6607 // Make a direct HTTP/2 request to proxy:70.
6608 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6609 HttpRequestInfo request1;
6610 request1.method = "GET";
6611 request1.url = GURL("https://proxy:70/");
6612 request1.traffic_annotation =
6613 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6614 HttpNetworkTransaction trans1(LOWEST, session.get());
6615 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
6616 NetLogWithSource())),
6617 IsOk());
6618 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6619 RunUntilIdle();
6620
6621 // Make a request using proxy:70 as a HTTP/2 proxy.
6622 capturing_proxy_resolver.set_proxy_server(
6623 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6624 HttpRequestInfo request2;
6625 request2.method = "GET";
6626 request2.url = GURL("https://www.example.org/");
6627 request2.traffic_annotation =
6628 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6629
6630 HttpNetworkTransaction trans2(LOWEST, session.get());
6631 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6632 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6633
6634 // Allow the SpdyProxyClientSocket's write callback to complete.
6635 base::RunLoop().RunUntilIdle();
6636 // Now allow the read of the response to complete.
6637 spdy_data2.Resume();
6638 rv = callback.WaitForResult();
6639 EXPECT_THAT(rv, IsOk());
6640
6641 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
6642 ASSERT_TRUE(response2);
6643 ASSERT_TRUE(response2->headers);
6644 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
6645
6646 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6647 EXPECT_EQ(kUploadData, response_data);
6648}
6649
[email protected]2df19bb2010-08-25 20:13:466650// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:016651TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:466652 HttpRequestInfo request;
6653 request.method = "GET";
bncce36dca22015-04-21 22:11:236654 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:466655 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:296656 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:106657 request.traffic_annotation =
6658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:466659
[email protected]79cb5c12011-09-12 13:12:046660 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496661 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6662 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516663 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076664 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096665 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276666
[email protected]2df19bb2010-08-25 20:13:466667 // Since we have proxy, should use full url
6668 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:166669 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6670 "Host: www.example.org\r\n"
6671 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466672
bnc691fda62016-08-12 00:43:166673 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:236674 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:166675 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6676 "Host: www.example.org\r\n"
6677 "Proxy-Connection: keep-alive\r\n"
6678 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466679 };
6680
6681 // The proxy responds to the GET with a 407, using a persistent
6682 // connection.
6683 MockRead data_reads1[] = {
6684 // No credentials.
6685 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6686 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6687 MockRead("Proxy-Connection: keep-alive\r\n"),
6688 MockRead("Content-Length: 0\r\n\r\n"),
6689
6690 MockRead("HTTP/1.1 200 OK\r\n"),
6691 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6692 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066693 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466694 };
6695
Ryan Sleevib8d7ea02018-05-07 20:01:016696 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076697 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066698 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076699 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466700
[email protected]49639fa2011-12-20 23:22:416701 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466702
bnc691fda62016-08-12 00:43:166703 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506704
bnc691fda62016-08-12 00:43:166705 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016706 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466707
6708 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016709 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466710
[email protected]58e32bb2013-01-21 18:23:256711 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166712 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256713 TestLoadTimingNotReused(load_timing_info,
6714 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6715
bnc691fda62016-08-12 00:43:166716 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526717 ASSERT_TRUE(response);
6718 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:466719 EXPECT_EQ(407, response->headers->response_code());
6720 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586721 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:506722 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466723
[email protected]49639fa2011-12-20 23:22:416724 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:466725
bnc691fda62016-08-12 00:43:166726 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016727 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466728
6729 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016730 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466731
[email protected]58e32bb2013-01-21 18:23:256732 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:166733 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256734 // Retrying with HTTP AUTH is considered to be reusing a socket.
6735 TestLoadTimingReused(load_timing_info);
6736
bnc691fda62016-08-12 00:43:166737 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526738 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466739
6740 EXPECT_TRUE(response->headers->IsKeepAlive());
6741 EXPECT_EQ(200, response->headers->response_code());
6742 EXPECT_EQ(100, response->headers->GetContentLength());
6743 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:506744 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466745
6746 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586747 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466748}
6749
[email protected]23e482282013-06-14 16:08:026750void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:086751 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:426752 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:086753 request.method = "GET";
bncce36dca22015-04-21 22:11:236754 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106755 request.traffic_annotation =
6756 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:086757
[email protected]cb9bf6ca2011-01-28 13:15:276758 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496759 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6760 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096761 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276762
[email protected]c744cf22009-02-27 07:28:086763 // Since we have proxy, should try to establish tunnel.
6764 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:176765 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6766 "Host: www.example.org:443\r\n"
6767 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:086768 };
6769
6770 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:236771 status, MockRead("Content-Length: 10\r\n\r\n"),
6772 // No response body because the test stops reading here.
6773 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:086774 };
6775
Ryan Sleevib8d7ea02018-05-07 20:01:016776 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:076777 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:086778
[email protected]49639fa2011-12-20 23:22:416779 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:086780
bnc691fda62016-08-12 00:43:166781 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506782
tfarina42834112016-09-22 13:38:206783 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016784 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:086785
6786 rv = callback.WaitForResult();
6787 EXPECT_EQ(expected_status, rv);
6788}
6789
[email protected]23e482282013-06-14 16:08:026790void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:236791 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:086792 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:426793 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:086794}
6795
bncd16676a2016-07-20 16:23:016796TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:086797 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
6798}
6799
bncd16676a2016-07-20 16:23:016800TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:086801 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
6802}
6803
bncd16676a2016-07-20 16:23:016804TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:086805 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
6806}
6807
bncd16676a2016-07-20 16:23:016808TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:086809 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
6810}
6811
bncd16676a2016-07-20 16:23:016812TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:086813 ConnectStatusHelper(
6814 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
6815}
6816
bncd16676a2016-07-20 16:23:016817TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:086818 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
6819}
6820
bncd16676a2016-07-20 16:23:016821TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:086822 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
6823}
6824
bncd16676a2016-07-20 16:23:016825TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:086826 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
6827}
6828
bncd16676a2016-07-20 16:23:016829TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:086830 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
6831}
6832
bncd16676a2016-07-20 16:23:016833TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:086834 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
6835}
6836
bncd16676a2016-07-20 16:23:016837TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:086838 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
6839}
6840
bncd16676a2016-07-20 16:23:016841TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:086842 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
6843}
6844
bncd16676a2016-07-20 16:23:016845TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:086846 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
6847}
6848
bncd16676a2016-07-20 16:23:016849TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:086850 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
6851}
6852
bncd16676a2016-07-20 16:23:016853TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:086854 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
6855}
6856
bncd16676a2016-07-20 16:23:016857TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:086858 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
6859}
6860
bncd16676a2016-07-20 16:23:016861TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:376862 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
6863}
6864
bncd16676a2016-07-20 16:23:016865TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:086866 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
6867}
6868
bncd16676a2016-07-20 16:23:016869TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:086870 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
6871}
6872
bncd16676a2016-07-20 16:23:016873TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:086874 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
6875}
6876
bncd16676a2016-07-20 16:23:016877TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:086878 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
6879}
6880
bncd16676a2016-07-20 16:23:016881TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:086882 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
6883}
6884
bncd16676a2016-07-20 16:23:016885TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:086886 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
6887}
6888
bncd16676a2016-07-20 16:23:016889TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:086890 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
6891}
6892
bncd16676a2016-07-20 16:23:016893TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:086894 ConnectStatusHelperWithExpectedStatus(
6895 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:546896 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:086897}
6898
bncd16676a2016-07-20 16:23:016899TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:086900 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
6901}
6902
bncd16676a2016-07-20 16:23:016903TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:086904 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
6905}
6906
bncd16676a2016-07-20 16:23:016907TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:086908 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
6909}
6910
bncd16676a2016-07-20 16:23:016911TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:086912 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
6913}
6914
bncd16676a2016-07-20 16:23:016915TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:086916 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
6917}
6918
bncd16676a2016-07-20 16:23:016919TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:086920 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
6921}
6922
bncd16676a2016-07-20 16:23:016923TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:086924 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
6925}
6926
bncd16676a2016-07-20 16:23:016927TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:086928 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
6929}
6930
bncd16676a2016-07-20 16:23:016931TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:086932 ConnectStatusHelper(
6933 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
6934}
6935
bncd16676a2016-07-20 16:23:016936TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:086937 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
6938}
6939
bncd16676a2016-07-20 16:23:016940TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:086941 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
6942}
6943
bncd16676a2016-07-20 16:23:016944TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:086945 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
6946}
6947
bncd16676a2016-07-20 16:23:016948TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:086949 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
6950}
6951
bncd16676a2016-07-20 16:23:016952TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:086953 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
6954}
6955
bncd16676a2016-07-20 16:23:016956TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:086957 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
6958}
6959
bncd16676a2016-07-20 16:23:016960TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:086961 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
6962}
6963
[email protected]038e9a32008-10-08 22:40:166964// Test the flow when both the proxy server AND origin server require
6965// authentication. Again, this uses basic auth for both since that is
6966// the simplest to mock.
bncd16676a2016-07-20 16:23:016967TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:276968 HttpRequestInfo request;
6969 request.method = "GET";
bncce36dca22015-04-21 22:11:236970 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106971 request.traffic_annotation =
6972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:276973
[email protected]038e9a32008-10-08 22:40:166974 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496975 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6976 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096977 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:076978
bnc691fda62016-08-12 00:43:166979 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:166980
[email protected]f9ee6b52008-11-08 06:46:236981 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236982 MockWrite(
6983 "GET http://www.example.org/ HTTP/1.1\r\n"
6984 "Host: www.example.org\r\n"
6985 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236986 };
6987
[email protected]038e9a32008-10-08 22:40:166988 MockRead data_reads1[] = {
6989 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
6990 // Give a couple authenticate options (only the middle one is actually
6991 // supported).
[email protected]22927ad2009-09-21 19:56:196992 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:166993 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6994 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
6995 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6996 // Large content-length -- won't matter, as connection will be reset.
6997 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066998 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:166999 };
7000
bnc691fda62016-08-12 00:43:167001 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167002 // request we should be issuing -- the final header line contains the
7003 // proxy's credentials.
7004 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237005 MockWrite(
7006 "GET http://www.example.org/ HTTP/1.1\r\n"
7007 "Host: www.example.org\r\n"
7008 "Proxy-Connection: keep-alive\r\n"
7009 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167010 };
7011
7012 // Now the proxy server lets the request pass through to origin server.
7013 // The origin server responds with a 401.
7014 MockRead data_reads2[] = {
7015 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7016 // Note: We are using the same realm-name as the proxy server. This is
7017 // completely valid, as realms are unique across hosts.
7018 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7019 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7020 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067021 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167022 };
7023
bnc691fda62016-08-12 00:43:167024 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167025 // the credentials for both the proxy and origin server.
7026 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237027 MockWrite(
7028 "GET http://www.example.org/ HTTP/1.1\r\n"
7029 "Host: www.example.org\r\n"
7030 "Proxy-Connection: keep-alive\r\n"
7031 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7032 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167033 };
7034
7035 // Lastly we get the desired content.
7036 MockRead data_reads3[] = {
7037 MockRead("HTTP/1.0 200 OK\r\n"),
7038 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7039 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067040 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167041 };
7042
Ryan Sleevib8d7ea02018-05-07 20:01:017043 StaticSocketDataProvider data1(data_reads1, data_writes1);
7044 StaticSocketDataProvider data2(data_reads2, data_writes2);
7045 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077046 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7047 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7048 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167049
[email protected]49639fa2011-12-20 23:22:417050 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167051
tfarina42834112016-09-22 13:38:207052 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017053 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167054
7055 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017056 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167057
bnc691fda62016-08-12 00:43:167058 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527059 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587060 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167061
[email protected]49639fa2011-12-20 23:22:417062 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167063
bnc691fda62016-08-12 00:43:167064 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017065 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167066
7067 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017068 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167069
bnc691fda62016-08-12 00:43:167070 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527071 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587072 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167073
[email protected]49639fa2011-12-20 23:22:417074 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167075
bnc691fda62016-08-12 00:43:167076 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7077 callback3.callback());
robpercival214763f2016-07-01 23:27:017078 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167079
7080 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017081 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167082
bnc691fda62016-08-12 00:43:167083 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587084 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167085 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167086}
[email protected]4ddaf2502008-10-23 18:26:197087
[email protected]ea9dc9a2009-09-05 00:43:327088// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7089// can't hook into its internals to cause it to generate predictable NTLM
7090// authorization headers.
7091#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377092// The NTLM authentication unit tests are based on known test data from the
7093// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7094// flow rather than the implementation of the NTLM protocol. See net/ntlm
7095// for the implementation and testing of the protocol.
7096//
7097// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297098
7099// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557100TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427101 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247102 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557103 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107104 request.traffic_annotation =
7105 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547106
7107 // Ensure load is not disrupted by flags which suppress behaviour specific
7108 // to other auth schemes.
7109 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247110
Zentaro Kavanagh6ccee512017-09-28 18:34:097111 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7112 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097113 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277114
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377115 // Generate the NTLM messages based on known test data.
7116 std::string negotiate_msg;
7117 std::string challenge_msg;
7118 std::string authenticate_msg;
7119 base::Base64Encode(
7120 base::StringPiece(
7121 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247122 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377123 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557124 base::Base64Encode(
7125 base::StringPiece(
7126 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247127 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557128 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377129 base::Base64Encode(
7130 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097131 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557132 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247133 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557134 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377135 &authenticate_msg);
7136
[email protected]3f918782009-02-28 01:29:247137 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557138 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7139 "Host: server\r\n"
7140 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247141 };
7142
7143 MockRead data_reads1[] = {
7144 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047145 // Negotiate and NTLM are often requested together. However, we only want
7146 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7147 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247148 MockRead("WWW-Authenticate: NTLM\r\n"),
7149 MockRead("Connection: close\r\n"),
7150 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367151 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247152 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247153 };
7154
7155 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167156 // After restarting with a null identity, this is the
7157 // request we should be issuing -- the final header line contains a Type
7158 // 1 message.
7159 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557160 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167161 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377162 "Authorization: NTLM "),
7163 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247164
bnc691fda62016-08-12 00:43:167165 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377166 // (using correct credentials). The second request continues on the
7167 // same connection.
bnc691fda62016-08-12 00:43:167168 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557169 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167170 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377171 "Authorization: NTLM "),
7172 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247173 };
7174
7175 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027176 // The origin server responds with a Type 2 message.
7177 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377178 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7179 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027180 MockRead("Content-Type: text/html\r\n\r\n"),
7181 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247182
Bence Béky1e4ef192017-09-18 19:58:027183 // Lastly we get the desired content.
7184 MockRead("HTTP/1.1 200 OK\r\n"),
7185 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7186 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247187 };
7188
Ryan Sleevib8d7ea02018-05-07 20:01:017189 StaticSocketDataProvider data1(data_reads1, data_writes1);
7190 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077191 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7192 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247193
Bence Béky83eb3512017-09-05 12:56:097194 SSLSocketDataProvider ssl1(ASYNC, OK);
7195 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7196 SSLSocketDataProvider ssl2(ASYNC, OK);
7197 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7198
[email protected]49639fa2011-12-20 23:22:417199 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247200
bnc691fda62016-08-12 00:43:167201 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507202
tfarina42834112016-09-22 13:38:207203 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017204 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247205
7206 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017207 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247208
bnc691fda62016-08-12 00:43:167209 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227210
bnc691fda62016-08-12 00:43:167211 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527212 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587213 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247214
[email protected]49639fa2011-12-20 23:22:417215 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257216
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377217 rv = trans.RestartWithAuth(
7218 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7219 callback2.callback());
robpercival214763f2016-07-01 23:27:017220 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257221
7222 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017223 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257224
bnc691fda62016-08-12 00:43:167225 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257226
bnc691fda62016-08-12 00:43:167227 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527228 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587229 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257230
[email protected]49639fa2011-12-20 23:22:417231 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247232
bnc691fda62016-08-12 00:43:167233 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017234 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247235
[email protected]0757e7702009-03-27 04:00:227236 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017237 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247238
bnc691fda62016-08-12 00:43:167239 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527240 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587241 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027242 EXPECT_EQ(14, response->headers->GetContentLength());
7243
7244 std::string response_data;
7245 rv = ReadTransaction(&trans, &response_data);
7246 EXPECT_THAT(rv, IsOk());
7247 EXPECT_EQ("Please Login\r\n", response_data);
7248
7249 EXPECT_TRUE(data1.AllReadDataConsumed());
7250 EXPECT_TRUE(data1.AllWriteDataConsumed());
7251 EXPECT_TRUE(data2.AllReadDataConsumed());
7252 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247253}
7254
[email protected]385a4672009-03-11 22:21:297255// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557256TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427257 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297258 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557259 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107260 request.traffic_annotation =
7261 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297262
Zentaro Kavanagh6ccee512017-09-28 18:34:097263 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7264 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097265 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277266
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377267 // Generate the NTLM messages based on known test data.
7268 std::string negotiate_msg;
7269 std::string challenge_msg;
7270 std::string authenticate_msg;
7271 base::Base64Encode(
7272 base::StringPiece(
7273 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247274 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377275 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557276 base::Base64Encode(
7277 base::StringPiece(
7278 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247279 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557280 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377281 base::Base64Encode(
7282 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097283 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557284 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247285 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557286 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377287 &authenticate_msg);
7288
7289 // The authenticate message when |kWrongPassword| is sent.
7290 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557291 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7292 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7293 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7294 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7295 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7296 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377297
Zentaro Kavanagh1890a3d2018-01-29 19:52:557298 // Sanity check that it's the same length as the correct authenticate message
7299 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377300 ASSERT_EQ(authenticate_msg.length(),
7301 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557302 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377303
[email protected]385a4672009-03-11 22:21:297304 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557305 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7306 "Host: server\r\n"
7307 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297308 };
7309
7310 MockRead data_reads1[] = {
7311 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047312 // Negotiate and NTLM are often requested together. However, we only want
7313 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7314 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297315 MockRead("WWW-Authenticate: NTLM\r\n"),
7316 MockRead("Connection: close\r\n"),
7317 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367318 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297319 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297320 };
7321
7322 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167323 // After restarting with a null identity, this is the
7324 // request we should be issuing -- the final header line contains a Type
7325 // 1 message.
7326 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557327 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167328 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377329 "Authorization: NTLM "),
7330 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297331
bnc691fda62016-08-12 00:43:167332 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377333 // (using incorrect credentials). The second request continues on the
7334 // same connection.
bnc691fda62016-08-12 00:43:167335 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557336 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167337 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377338 "Authorization: NTLM "),
7339 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297340 };
7341
7342 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377343 // The origin server responds with a Type 2 message.
7344 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7345 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7346 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
7347 MockRead("Content-Type: text/html\r\n\r\n"),
7348 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297349
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377350 // Wrong password.
7351 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7352 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
7353 MockRead("Content-Length: 42\r\n"),
7354 MockRead("Content-Type: text/html\r\n\r\n"),
7355 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297356 };
7357
7358 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:167359 // After restarting with a null identity, this is the
7360 // request we should be issuing -- the final header line contains a Type
7361 // 1 message.
7362 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557363 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167364 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377365 "Authorization: NTLM "),
7366 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297367
bnc691fda62016-08-12 00:43:167368 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7369 // (the credentials for the origin server). The second request continues
7370 // on the same connection.
7371 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557372 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167373 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377374 "Authorization: NTLM "),
7375 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297376 };
7377
7378 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:027379 // The origin server responds with a Type 2 message.
7380 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377381 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7382 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027383 MockRead("Content-Type: text/html\r\n\r\n"),
7384 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297385
Bence Béky1e4ef192017-09-18 19:58:027386 // Lastly we get the desired content.
7387 MockRead("HTTP/1.1 200 OK\r\n"),
7388 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7389 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:297390 };
7391
Ryan Sleevib8d7ea02018-05-07 20:01:017392 StaticSocketDataProvider data1(data_reads1, data_writes1);
7393 StaticSocketDataProvider data2(data_reads2, data_writes2);
7394 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077395 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7396 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7397 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:297398
Bence Béky83eb3512017-09-05 12:56:097399 SSLSocketDataProvider ssl1(ASYNC, OK);
7400 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7401 SSLSocketDataProvider ssl2(ASYNC, OK);
7402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7403 SSLSocketDataProvider ssl3(ASYNC, OK);
7404 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7405
[email protected]49639fa2011-12-20 23:22:417406 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:297407
bnc691fda62016-08-12 00:43:167408 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507409
tfarina42834112016-09-22 13:38:207410 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017411 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297412
7413 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017414 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297415
bnc691fda62016-08-12 00:43:167416 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:297417
bnc691fda62016-08-12 00:43:167418 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527419 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587420 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:297421
[email protected]49639fa2011-12-20 23:22:417422 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:297423
[email protected]0757e7702009-03-27 04:00:227424 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377425 rv = trans.RestartWithAuth(
7426 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
7427 callback2.callback());
robpercival214763f2016-07-01 23:27:017428 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297429
[email protected]10af5fe72011-01-31 16:17:257430 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017431 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297432
bnc691fda62016-08-12 00:43:167433 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417434 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:167435 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017436 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257437 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017438 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:167439 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227440
bnc691fda62016-08-12 00:43:167441 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527442 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587443 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:227444
[email protected]49639fa2011-12-20 23:22:417445 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:227446
7447 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377448 rv = trans.RestartWithAuth(
7449 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7450 callback4.callback());
robpercival214763f2016-07-01 23:27:017451 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257452
7453 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:017454 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257455
bnc691fda62016-08-12 00:43:167456 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257457
[email protected]49639fa2011-12-20 23:22:417458 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:257459
7460 // One more roundtrip
bnc691fda62016-08-12 00:43:167461 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:017462 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227463
7464 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:017465 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227466
bnc691fda62016-08-12 00:43:167467 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587468 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027469 EXPECT_EQ(14, response->headers->GetContentLength());
7470
7471 std::string response_data;
7472 rv = ReadTransaction(&trans, &response_data);
7473 EXPECT_THAT(rv, IsOk());
7474 EXPECT_EQ("Please Login\r\n", response_data);
7475
7476 EXPECT_TRUE(data1.AllReadDataConsumed());
7477 EXPECT_TRUE(data1.AllWriteDataConsumed());
7478 EXPECT_TRUE(data2.AllReadDataConsumed());
7479 EXPECT_TRUE(data2.AllWriteDataConsumed());
7480 EXPECT_TRUE(data3.AllReadDataConsumed());
7481 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:297482}
Bence Béky83eb3512017-09-05 12:56:097483
Bence Béky3238f2e12017-09-22 22:44:497484// Server requests NTLM authentication, which is not supported over HTTP/2.
7485// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:097486TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:097487 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7488 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:097489
Zentaro Kavanagh1890a3d2018-01-29 19:52:557490 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:097491
7492 HttpRequestInfo request;
7493 request.method = "GET";
7494 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:107495 request.traffic_annotation =
7496 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:097497
7498 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:137499 spdy::SpdyHeaderBlock request_headers0(
7500 spdy_util_.ConstructGetHeaderBlock(kUrl));
7501 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:097502 1, std::move(request_headers0), LOWEST, true));
7503
Ryan Hamilton0239aac2018-05-19 00:03:137504 spdy::SpdyHeaderBlock response_headers0;
7505 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:097506 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:137507 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:097508 1, std::move(response_headers0), true));
7509
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377510 // Stream 1 is closed.
7511 spdy_util_.UpdateWithStreamDestruction(1);
7512
7513 // Generate the NTLM messages based on known test data.
7514 std::string negotiate_msg;
7515 std::string challenge_msg;
7516 std::string authenticate_msg;
7517 base::Base64Encode(
7518 base::StringPiece(
7519 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247520 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377521 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557522 base::Base64Encode(
7523 base::StringPiece(
7524 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247525 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557526 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377527 base::Base64Encode(
7528 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097529 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557530 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247531 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557532 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377533 &authenticate_msg);
7534
Bence Béky3238f2e12017-09-22 22:44:497535 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
Matt Menke6082f952019-08-21 16:23:167536 MockRead reads0[] = {CreateMockRead(resp, 1),
7537 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
Bence Béky83eb3512017-09-05 12:56:097538
7539 // Retry yet again using HTTP/1.1.
7540 MockWrite writes1[] = {
7541 // After restarting with a null identity, this is the
7542 // request we should be issuing -- the final header line contains a Type
7543 // 1 message.
7544 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557545 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097546 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377547 "Authorization: NTLM "),
7548 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097549
7550 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7551 // (the credentials for the origin server). The second request continues
7552 // on the same connection.
7553 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557554 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097555 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377556 "Authorization: NTLM "),
7557 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097558 };
7559
7560 MockRead reads1[] = {
7561 // The origin server responds with a Type 2 message.
7562 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377563 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7564 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:097565 MockRead("Content-Type: text/html\r\n\r\n"),
7566 MockRead("You are not authorized to view this page\r\n"),
7567
7568 // Lastly we get the desired content.
7569 MockRead("HTTP/1.1 200 OK\r\n"),
7570 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027571 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:097572 };
Ryan Sleevib8d7ea02018-05-07 20:01:017573 SequencedSocketData data0(reads0, writes0);
7574 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:097575 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7576 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7577
7578 SSLSocketDataProvider ssl0(ASYNC, OK);
7579 ssl0.next_proto = kProtoHTTP2;
Matt Menke6082f952019-08-21 16:23:167580 ssl0.next_protos_expected_in_ssl_config =
7581 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:097582 SSLSocketDataProvider ssl1(ASYNC, OK);
Matt Menke6082f952019-08-21 16:23:167583 // When creating the second connection, only HTTP/1.1 should be allowed.
7584 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
Bence Béky83eb3512017-09-05 12:56:097585 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7587
7588 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7589 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7590
7591 TestCompletionCallback callback1;
7592 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
7593 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7594
7595 rv = callback1.WaitForResult();
7596 EXPECT_THAT(rv, IsOk());
7597
7598 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7599
7600 const HttpResponseInfo* response = trans.GetResponseInfo();
7601 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587602 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:097603
7604 TestCompletionCallback callback2;
7605
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377606 rv = trans.RestartWithAuth(
7607 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7608 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:097609 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7610
7611 rv = callback2.WaitForResult();
7612 EXPECT_THAT(rv, IsOk());
7613
7614 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7615
7616 response = trans.GetResponseInfo();
7617 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587618 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:097619
7620 TestCompletionCallback callback3;
7621
7622 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
7623 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7624
7625 rv = callback3.WaitForResult();
7626 EXPECT_THAT(rv, IsOk());
7627
7628 response = trans.GetResponseInfo();
7629 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587630 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027631 EXPECT_EQ(14, response->headers->GetContentLength());
7632
7633 std::string response_data;
7634 rv = ReadTransaction(&trans, &response_data);
7635 EXPECT_THAT(rv, IsOk());
7636 EXPECT_EQ("Please Login\r\n", response_data);
7637
7638 EXPECT_TRUE(data0.AllReadDataConsumed());
7639 EXPECT_TRUE(data0.AllWriteDataConsumed());
7640 EXPECT_TRUE(data1.AllReadDataConsumed());
7641 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:097642}
David Benjamin5cb91132018-04-06 05:54:497643
Matt Menkef2ee07c2019-08-29 02:10:367644#if BUILDFLAG(ENABLE_WEBSOCKETS)
7645
7646// Variant of above test using WebSockets.
7647TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
7648 const GURL kInitialUrl("https://server/");
7649 const GURL kWebSocketUrl("wss://server/");
7650 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7651 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7652
7653 // Initial request establishes an H2 connection, which will then be reused for
7654 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
7655 // it won't create a new one.
7656 spdy::SpdyHeaderBlock initial_request_headers(
7657 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
7658 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
7659 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
7660 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
7661
7662 // Settings frame, indicating WebSockets is supported.
7663 spdy::SettingsMap settings;
7664 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
7665 spdy::SpdySerializedFrame settings_frame(
7666 spdy_util_.ConstructSpdySettings(settings));
7667
7668 // Response headers for first request. Body is never received, but that
7669 // shouldn't matter for the purposes of this test.
7670 spdy::SpdySerializedFrame initial_response(
7671 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7672
7673 // First WebSocket request, which has no credentials.
7674 spdy::SpdyHeaderBlock websocket_request_headers;
7675 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
7676 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
7677 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
7678 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
7679 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
7680 websocket_request_headers["origin"] = "http://server";
7681 websocket_request_headers["sec-websocket-version"] = "13";
7682 websocket_request_headers["sec-websocket-extensions"] =
7683 "permessage-deflate; client_max_window_bits";
7684 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
7685 3, std::move(websocket_request_headers), MEDIUM, false));
7686
7687 // Auth challenge to WebSocket request.
7688 spdy::SpdyHeaderBlock auth_challenge_headers;
7689 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
7690 auth_challenge_headers["www-authenticate"] = "NTLM";
7691 spdy::SpdySerializedFrame websocket_auth_challenge(
7692 spdy_util_.ConstructSpdyResponseHeaders(
7693 3, std::move(auth_challenge_headers), true));
7694
7695 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
7696 CreateMockWrite(settings_ack, 2),
7697 CreateMockWrite(websocket_request, 4),
7698 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
7699 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
7700 CreateMockRead(initial_response, 3),
7701 CreateMockRead(websocket_auth_challenge, 5),
7702 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
7703
7704 // Generate the NTLM messages based on known test data.
7705 std::string negotiate_msg;
7706 std::string challenge_msg;
7707 std::string authenticate_msg;
7708 base::Base64Encode(
7709 base::StringPiece(
7710 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
7711 base::size(ntlm::test::kExpectedNegotiateMsg)),
7712 &negotiate_msg);
7713 base::Base64Encode(
7714 base::StringPiece(
7715 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
7716 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
7717 &challenge_msg);
7718 base::Base64Encode(
7719 base::StringPiece(
7720 reinterpret_cast<const char*>(
7721 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
7722 base::size(
7723 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7724 &authenticate_msg);
7725
7726 // Retry yet again using HTTP/1.1.
7727 MockWrite writes1[] = {
7728 // After restarting with a null identity, this is the
7729 // request we should be issuing -- the final header line contains a Type
7730 // 1 message.
7731 MockWrite("GET / HTTP/1.1\r\n"
7732 "Host: server\r\n"
7733 "Connection: Upgrade\r\n"
7734 "Authorization: NTLM "),
7735 MockWrite(negotiate_msg.c_str()),
7736 MockWrite("\r\n"),
7737 MockWrite("Origin: http://server\r\n"
7738 "Sec-WebSocket-Version: 13\r\n"
7739 "Upgrade: websocket\r\n"
7740 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7741 "Sec-WebSocket-Extensions: permessage-deflate; "
7742 "client_max_window_bits\r\n\r\n"),
7743
7744 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7745 // (the credentials for the origin server). The second request continues
7746 // on the same connection.
7747 MockWrite("GET / HTTP/1.1\r\n"
7748 "Host: server\r\n"
7749 "Connection: Upgrade\r\n"
7750 "Authorization: NTLM "),
7751 MockWrite(authenticate_msg.c_str()),
7752 MockWrite("\r\n"),
7753 MockWrite("Origin: http://server\r\n"
7754 "Sec-WebSocket-Version: 13\r\n"
7755 "Upgrade: websocket\r\n"
7756 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
7757 "Sec-WebSocket-Extensions: permessage-deflate; "
7758 "client_max_window_bits\r\n\r\n"),
7759 };
7760
7761 MockRead reads1[] = {
7762 // The origin server responds with a Type 2 message.
7763 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7764 MockRead("WWW-Authenticate: NTLM "),
7765 MockRead(challenge_msg.c_str()),
7766 MockRead("\r\n"),
7767 MockRead("Content-Length: 42\r\n"),
7768 MockRead("Content-Type: text/html\r\n\r\n"),
7769 MockRead("You are not authorized to view this page\r\n"),
7770
7771 // Lastly we get the desired content.
7772 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
7773 "Upgrade: websocket\r\n"
7774 "Connection: Upgrade\r\n"
7775 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
7776 };
7777 SequencedSocketData data0(reads0, writes0);
7778 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7779 SSLSocketDataProvider ssl0(ASYNC, OK);
7780 ssl0.next_proto = kProtoHTTP2;
7781 ssl0.next_protos_expected_in_ssl_config =
7782 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
7783 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7784
7785 StaticSocketDataProvider data1(reads1, writes1);
7786 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7787 SSLSocketDataProvider ssl1(ASYNC, OK);
7788 // When creating the second connection, only HTTP/1.1 should be allowed.
7789 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{};
7790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7791
7792 session_deps_.enable_websocket_over_http2 = true;
7793 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7794
7795 HttpRequestInfo initial_request_info;
7796 initial_request_info.method = "GET";
7797 initial_request_info.url = kInitialUrl;
7798 initial_request_info.traffic_annotation =
7799 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7800 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
7801 TestCompletionCallback initial_callback;
7802 int rv = initial_trans.Start(&initial_request_info,
7803 initial_callback.callback(), NetLogWithSource());
7804 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
7805
7806 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
7807 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
7808
7809 HttpRequestInfo websocket_request_info;
7810 websocket_request_info.method = "GET";
7811 websocket_request_info.url = kWebSocketUrl;
7812 websocket_request_info.traffic_annotation =
7813 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7814 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
7815 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
7816 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
7817 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
7818 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
7819 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
7820 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
7821
7822 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
7823
7824 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
7825 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
7826 &websocket_stream_create_helper);
7827
7828 TestCompletionCallback websocket_callback;
7829 rv = websocket_trans.Start(&websocket_request_info,
7830 websocket_callback.callback(), NetLogWithSource());
7831 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7832
7833 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
7834
7835 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
7836 ASSERT_TRUE(response);
7837 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
7838
7839 rv = websocket_trans.RestartWithAuth(
7840 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7841 websocket_callback.callback());
7842 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7843
7844 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
7845
7846 response = websocket_trans.GetResponseInfo();
7847 ASSERT_TRUE(response);
7848 EXPECT_FALSE(response->auth_challenge.has_value());
7849
7850 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
7851 websocket_callback.callback());
7852 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
7853
7854 // The server should have been marked as requiring HTTP/1.1. The important
7855 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
7856 // WSS.
7857 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
7858 url::SchemeHostPort(kInitialUrl), NetworkIsolationKey()));
7859}
7860
7861#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
7862
David Benjamin5cb91132018-04-06 05:54:497863// Test that, if we have an NTLM proxy and the origin resets the connection, we
7864// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:377865// regression test for https://crbug.com/823387. The version interference probe
7866// has since been removed, but retain the regression test so we can update it if
7867// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:497868TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
7869 // The NTLM test data expects the proxy to be named 'server'. The origin is
7870 // https://origin/.
7871 session_deps_.proxy_resolution_service =
7872 ProxyResolutionService::CreateFixedFromPacResult(
7873 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
7874
David Benjamin151ec6b2019-08-02 19:38:527875 SSLContextConfig config;
David Benjamin5cb91132018-04-06 05:54:497876 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:077877 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:497878
7879 HttpRequestInfo request;
7880 request.method = "GET";
7881 request.url = GURL("https://origin/");
7882 request.traffic_annotation =
7883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7884
7885 // Ensure load is not disrupted by flags which suppress behaviour specific
7886 // to other auth schemes.
7887 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
7888
7889 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7890 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7891 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7892
7893 // Generate the NTLM messages based on known test data.
7894 std::string negotiate_msg;
7895 std::string challenge_msg;
7896 std::string authenticate_msg;
7897 base::Base64Encode(
7898 base::StringPiece(
7899 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247900 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:497901 &negotiate_msg);
7902 base::Base64Encode(
7903 base::StringPiece(
7904 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247905 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:497906 &challenge_msg);
7907 base::Base64Encode(
7908 base::StringPiece(
7909 reinterpret_cast<const char*>(
7910 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247911 base::size(
David Benjamin5cb91132018-04-06 05:54:497912 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7913 &authenticate_msg);
7914
7915 MockWrite data_writes[] = {
7916 // The initial CONNECT request.
7917 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7918 "Host: origin:443\r\n"
7919 "Proxy-Connection: keep-alive\r\n\r\n"),
7920
7921 // After restarting with an identity.
7922 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7923 "Host: origin:443\r\n"
7924 "Proxy-Connection: keep-alive\r\n"
7925 "Proxy-Authorization: NTLM "),
7926 MockWrite(negotiate_msg.c_str()),
7927 // End headers.
7928 MockWrite("\r\n\r\n"),
7929
7930 // The second restart.
7931 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7932 "Host: origin:443\r\n"
7933 "Proxy-Connection: keep-alive\r\n"
7934 "Proxy-Authorization: NTLM "),
7935 MockWrite(authenticate_msg.c_str()),
7936 // End headers.
7937 MockWrite("\r\n\r\n"),
7938 };
7939
7940 MockRead data_reads[] = {
7941 // The initial NTLM response.
7942 MockRead("HTTP/1.1 407 Access Denied\r\n"
7943 "Content-Length: 0\r\n"
7944 "Proxy-Authenticate: NTLM\r\n\r\n"),
7945
7946 // The NTLM challenge message.
7947 MockRead("HTTP/1.1 407 Access Denied\r\n"
7948 "Content-Length: 0\r\n"
7949 "Proxy-Authenticate: NTLM "),
7950 MockRead(challenge_msg.c_str()),
7951 // End headers.
7952 MockRead("\r\n\r\n"),
7953
7954 // Finally the tunnel is established.
7955 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
7956 };
7957
Ryan Sleevib8d7ea02018-05-07 20:01:017958 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:497959 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:497960 session_deps_.socket_factory->AddSocketDataProvider(&data);
7961 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:497962
7963 // Start the transaction. The proxy responds with an NTLM authentication
7964 // request.
7965 TestCompletionCallback callback;
7966 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7967 int rv = callback.GetResult(
7968 trans.Start(&request, callback.callback(), NetLogWithSource()));
7969
7970 EXPECT_THAT(rv, IsOk());
7971 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7972 const HttpResponseInfo* response = trans.GetResponseInfo();
7973 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587974 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:497975
David Benjamind61bd532019-04-23 21:11:377976 // Configure credentials and restart. The proxy responds with the challenge
7977 // message.
David Benjamin5cb91132018-04-06 05:54:497978 rv = callback.GetResult(trans.RestartWithAuth(
7979 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7980 callback.callback()));
7981 EXPECT_THAT(rv, IsOk());
7982 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7983 response = trans.GetResponseInfo();
7984 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587985 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:497986
David Benjamind61bd532019-04-23 21:11:377987 // Restart once more. The tunnel will be established and then the SSL
7988 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:497989 rv = callback.GetResult(
7990 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
7991 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
7992}
7993
[email protected]ea9dc9a2009-09-05 00:43:327994#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:297995
[email protected]4ddaf2502008-10-23 18:26:197996// Test reading a server response which has only headers, and no body.
7997// After some maximum number of bytes is consumed, the transaction should
7998// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:017999TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:428000 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:198001 request.method = "GET";
bncce36dca22015-04-21 22:11:238002 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108003 request.traffic_annotation =
8004 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:198005
danakj1fd259a02016-04-16 03:17:098006 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168007 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278008
[email protected]b75b7b2f2009-10-06 00:54:538009 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:438010 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:538011 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:198012
8013 MockRead data_reads[] = {
8014 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:068015 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:198016 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:068017 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:198018 };
Ryan Sleevib8d7ea02018-05-07 20:01:018019 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078020 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:198021
[email protected]49639fa2011-12-20 23:22:418022 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:198023
tfarina42834112016-09-22 13:38:208024 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018025 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:198026
8027 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018028 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:198029}
[email protected]f4e426b2008-11-05 00:24:498030
8031// Make sure that we don't try to reuse a TCPClientSocket when failing to
8032// establish tunnel.
8033// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:018034TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:278035 HttpRequestInfo request;
8036 request.method = "GET";
bncce36dca22015-04-21 22:11:238037 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108038 request.traffic_annotation =
8039 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:278040
[email protected]f4e426b2008-11-05 00:24:498041 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:498042 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
8043 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:018044
danakj1fd259a02016-04-16 03:17:098045 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:498046
bnc87dcefc2017-05-25 12:47:588047 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198048 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:498049
[email protected]f4e426b2008-11-05 00:24:498050 // Since we have proxy, should try to establish tunnel.
8051 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:178052 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8053 "Host: www.example.org:443\r\n"
8054 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:498055 };
8056
[email protected]77848d12008-11-14 00:00:228057 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:498058 // connection. Usually a proxy would return 501 (not implemented),
8059 // or 200 (tunnel established).
8060 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:238061 MockRead("HTTP/1.1 404 Not Found\r\n"),
8062 MockRead("Content-Length: 10\r\n\r\n"),
8063 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:498064 };
8065
Ryan Sleevib8d7ea02018-05-07 20:01:018066 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078067 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:498068
[email protected]49639fa2011-12-20 23:22:418069 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:498070
tfarina42834112016-09-22 13:38:208071 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018072 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:498073
8074 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018075 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:498076
[email protected]b4404c02009-04-10 16:38:528077 // Empty the current queue. This is necessary because idle sockets are
8078 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558079 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528080
[email protected]f4e426b2008-11-05 00:24:498081 // We now check to make sure the TCPClientSocket was not added back to
8082 // the pool.
[email protected]90499482013-06-01 00:39:508083 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498084 trans.reset();
fdoray92e35a72016-06-10 15:54:558085 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:498086 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:508087 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:498088}
[email protected]372d34a2008-11-05 21:30:518089
[email protected]1b157c02009-04-21 01:55:408090// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:018091TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:428092 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:408093 request.method = "GET";
bncce36dca22015-04-21 22:11:238094 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108095 request.traffic_annotation =
8096 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:408097
danakj1fd259a02016-04-16 03:17:098098 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278099
bnc691fda62016-08-12 00:43:168100 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278101
[email protected]1b157c02009-04-21 01:55:408102 MockRead data_reads[] = {
8103 // A part of the response body is received with the response headers.
8104 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8105 // The rest of the response body is received in two parts.
8106 MockRead("lo"),
8107 MockRead(" world"),
8108 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068109 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:408110 };
8111
Ryan Sleevib8d7ea02018-05-07 20:01:018112 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078113 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:408114
[email protected]49639fa2011-12-20 23:22:418115 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:408116
tfarina42834112016-09-22 13:38:208117 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:408119
8120 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018121 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408122
bnc691fda62016-08-12 00:43:168123 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528124 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:408125
wezca1070932016-05-26 20:30:528126 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:408127 std::string status_line = response->headers->GetStatusLine();
8128 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8129
[email protected]90499482013-06-01 00:39:508130 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408131
8132 std::string response_data;
bnc691fda62016-08-12 00:43:168133 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018134 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:408135 EXPECT_EQ("hello world", response_data);
8136
8137 // Empty the current queue. This is necessary because idle sockets are
8138 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558139 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:408140
8141 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508142 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:408143}
8144
[email protected]76a505b2010-08-25 06:23:008145// Make sure that we recycle a SSL socket after reading all of the response
8146// body.
bncd16676a2016-07-20 16:23:018147TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008148 HttpRequestInfo request;
8149 request.method = "GET";
bncce36dca22015-04-21 22:11:238150 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108151 request.traffic_annotation =
8152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008153
8154 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238155 MockWrite(
8156 "GET / HTTP/1.1\r\n"
8157 "Host: www.example.org\r\n"
8158 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008159 };
8160
8161 MockRead data_reads[] = {
8162 MockRead("HTTP/1.1 200 OK\r\n"),
8163 MockRead("Content-Length: 11\r\n\r\n"),
8164 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068165 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008166 };
8167
[email protected]8ddf8322012-02-23 18:08:068168 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078169 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008170
Ryan Sleevib8d7ea02018-05-07 20:01:018171 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078172 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008173
[email protected]49639fa2011-12-20 23:22:418174 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008175
danakj1fd259a02016-04-16 03:17:098176 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168177 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008178
tfarina42834112016-09-22 13:38:208179 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008180
robpercival214763f2016-07-01 23:27:018181 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8182 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008183
bnc691fda62016-08-12 00:43:168184 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528185 ASSERT_TRUE(response);
8186 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008187 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8188
[email protected]90499482013-06-01 00:39:508189 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008190
8191 std::string response_data;
bnc691fda62016-08-12 00:43:168192 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018193 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008194 EXPECT_EQ("hello world", response_data);
8195
8196 // Empty the current queue. This is necessary because idle sockets are
8197 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558198 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008199
8200 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238201 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008202}
8203
8204// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8205// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018206TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008207 HttpRequestInfo request;
8208 request.method = "GET";
bncce36dca22015-04-21 22:11:238209 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108210 request.traffic_annotation =
8211 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008212
8213 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238214 MockWrite(
8215 "GET / HTTP/1.1\r\n"
8216 "Host: www.example.org\r\n"
8217 "Connection: keep-alive\r\n\r\n"),
8218 MockWrite(
8219 "GET / HTTP/1.1\r\n"
8220 "Host: www.example.org\r\n"
8221 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008222 };
8223
8224 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428225 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8226 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008227
[email protected]8ddf8322012-02-23 18:08:068228 SSLSocketDataProvider ssl(ASYNC, OK);
8229 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078230 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008232
Ryan Sleevib8d7ea02018-05-07 20:01:018233 StaticSocketDataProvider data(data_reads, data_writes);
8234 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078235 session_deps_.socket_factory->AddSocketDataProvider(&data);
8236 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008237
[email protected]49639fa2011-12-20 23:22:418238 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008239
danakj1fd259a02016-04-16 03:17:098240 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588241 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198242 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008243
tfarina42834112016-09-22 13:38:208244 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008245
robpercival214763f2016-07-01 23:27:018246 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8247 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008248
8249 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528250 ASSERT_TRUE(response);
8251 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008252 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8253
[email protected]90499482013-06-01 00:39:508254 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008255
8256 std::string response_data;
8257 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018258 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008259 EXPECT_EQ("hello world", response_data);
8260
8261 // Empty the current queue. This is necessary because idle sockets are
8262 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558263 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008264
8265 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238266 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008267
8268 // Now start the second transaction, which should reuse the previous socket.
8269
bnc87dcefc2017-05-25 12:47:588270 trans =
Jeremy Roman0579ed62017-08-29 15:56:198271 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008272
tfarina42834112016-09-22 13:38:208273 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008274
robpercival214763f2016-07-01 23:27:018275 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8276 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008277
8278 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528279 ASSERT_TRUE(response);
8280 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008281 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8282
[email protected]90499482013-06-01 00:39:508283 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008284
8285 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018286 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008287 EXPECT_EQ("hello world", response_data);
8288
8289 // Empty the current queue. This is necessary because idle sockets are
8290 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558291 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008292
8293 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238294 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008295}
8296
maksim.sisov0adf8592016-07-15 06:25:568297// Grab a socket, use it, and put it back into the pool. Then, make
8298// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018299TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568300 HttpRequestInfo request;
8301 request.method = "GET";
8302 request.url = GURL("http://www.example.org/");
8303 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108304 request.traffic_annotation =
8305 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568306
8307 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8308
bnc691fda62016-08-12 00:43:168309 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568310
8311 MockRead data_reads[] = {
8312 // A part of the response body is received with the response headers.
8313 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8314 // The rest of the response body is received in two parts.
8315 MockRead("lo"), MockRead(" world"),
8316 MockRead("junk"), // Should not be read!!
8317 MockRead(SYNCHRONOUS, OK),
8318 };
8319
Ryan Sleevib8d7ea02018-05-07 20:01:018320 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:568321 session_deps_.socket_factory->AddSocketDataProvider(&data);
8322
8323 TestCompletionCallback callback;
8324
tfarina42834112016-09-22 13:38:208325 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568326 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8327
8328 EXPECT_THAT(callback.GetResult(rv), IsOk());
8329
bnc691fda62016-08-12 00:43:168330 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568331 ASSERT_TRUE(response);
8332 EXPECT_TRUE(response->headers);
8333 std::string status_line = response->headers->GetStatusLine();
8334 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8335
8336 // Make memory critical notification and ensure the transaction still has been
8337 // operating right.
8338 base::MemoryPressureListener::NotifyMemoryPressure(
8339 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8340 base::RunLoop().RunUntilIdle();
8341
8342 // Socket should not be flushed as long as it is not idle.
8343 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8344
8345 std::string response_data;
bnc691fda62016-08-12 00:43:168346 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568347 EXPECT_THAT(rv, IsOk());
8348 EXPECT_EQ("hello world", response_data);
8349
8350 // Empty the current queue. This is necessary because idle sockets are
8351 // added to the connection pool asynchronously with a PostTask.
8352 base::RunLoop().RunUntilIdle();
8353
8354 // We now check to make sure the socket was added back to the pool.
8355 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8356
8357 // Idle sockets should be flushed now.
8358 base::MemoryPressureListener::NotifyMemoryPressure(
8359 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8360 base::RunLoop().RunUntilIdle();
8361
8362 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8363}
8364
yucliu48f235d2018-01-11 00:59:558365// Disable idle socket closing on memory pressure.
8366// Grab a socket, use it, and put it back into the pool. Then, make
8367// low memory notification and ensure the socket pool is NOT flushed.
8368TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
8369 HttpRequestInfo request;
8370 request.method = "GET";
8371 request.url = GURL("http://www.example.org/");
8372 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108373 request.traffic_annotation =
8374 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:558375
8376 // Disable idle socket closing on memory pressure.
8377 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
8378 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8379
8380 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8381
8382 MockRead data_reads[] = {
8383 // A part of the response body is received with the response headers.
8384 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8385 // The rest of the response body is received in two parts.
8386 MockRead("lo"), MockRead(" world"),
8387 MockRead("junk"), // Should not be read!!
8388 MockRead(SYNCHRONOUS, OK),
8389 };
8390
Ryan Sleevib8d7ea02018-05-07 20:01:018391 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:558392 session_deps_.socket_factory->AddSocketDataProvider(&data);
8393
8394 TestCompletionCallback callback;
8395
8396 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
8397 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8398
8399 EXPECT_THAT(callback.GetResult(rv), IsOk());
8400
8401 const HttpResponseInfo* response = trans.GetResponseInfo();
8402 ASSERT_TRUE(response);
8403 EXPECT_TRUE(response->headers);
8404 std::string status_line = response->headers->GetStatusLine();
8405 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8406
8407 // Make memory critical notification and ensure the transaction still has been
8408 // operating right.
8409 base::MemoryPressureListener::NotifyMemoryPressure(
8410 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8411 base::RunLoop().RunUntilIdle();
8412
8413 // Socket should not be flushed as long as it is not idle.
8414 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8415
8416 std::string response_data;
8417 rv = ReadTransaction(&trans, &response_data);
8418 EXPECT_THAT(rv, IsOk());
8419 EXPECT_EQ("hello world", response_data);
8420
8421 // Empty the current queue. This is necessary because idle sockets are
8422 // added to the connection pool asynchronously with a PostTask.
8423 base::RunLoop().RunUntilIdle();
8424
8425 // We now check to make sure the socket was added back to the pool.
8426 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8427
8428 // Idle sockets should NOT be flushed on moderate memory pressure.
8429 base::MemoryPressureListener::NotifyMemoryPressure(
8430 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
8431 base::RunLoop().RunUntilIdle();
8432
8433 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8434
8435 // Idle sockets should NOT be flushed on critical memory pressure.
8436 base::MemoryPressureListener::NotifyMemoryPressure(
8437 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8438 base::RunLoop().RunUntilIdle();
8439
8440 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8441}
8442
maksim.sisov0adf8592016-07-15 06:25:568443// Grab an SSL socket, use it, and put it back into the pool. Then, make
8444// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018445TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568446 HttpRequestInfo request;
8447 request.method = "GET";
8448 request.url = GURL("https://www.example.org/");
8449 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108450 request.traffic_annotation =
8451 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568452
8453 MockWrite data_writes[] = {
8454 MockWrite("GET / HTTP/1.1\r\n"
8455 "Host: www.example.org\r\n"
8456 "Connection: keep-alive\r\n\r\n"),
8457 };
8458
8459 MockRead data_reads[] = {
8460 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8461 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
8462
8463 SSLSocketDataProvider ssl(ASYNC, OK);
8464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8465
Ryan Sleevib8d7ea02018-05-07 20:01:018466 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:568467 session_deps_.socket_factory->AddSocketDataProvider(&data);
8468
8469 TestCompletionCallback callback;
8470
8471 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168472 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568473
Matt Menke9d5e2c92019-02-05 01:42:238474 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:208475 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568476
8477 EXPECT_THAT(callback.GetResult(rv), IsOk());
8478
bnc691fda62016-08-12 00:43:168479 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568480 ASSERT_TRUE(response);
8481 ASSERT_TRUE(response->headers);
8482 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8483
8484 // Make memory critical notification and ensure the transaction still has been
8485 // operating right.
8486 base::MemoryPressureListener::NotifyMemoryPressure(
8487 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8488 base::RunLoop().RunUntilIdle();
8489
Matt Menke9d5e2c92019-02-05 01:42:238490 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568491
8492 std::string response_data;
bnc691fda62016-08-12 00:43:168493 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568494 EXPECT_THAT(rv, IsOk());
8495 EXPECT_EQ("hello world", response_data);
8496
8497 // Empty the current queue. This is necessary because idle sockets are
8498 // added to the connection pool asynchronously with a PostTask.
8499 base::RunLoop().RunUntilIdle();
8500
8501 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238502 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568503
8504 // Make memory notification once again and ensure idle socket is closed.
8505 base::MemoryPressureListener::NotifyMemoryPressure(
8506 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8507 base::RunLoop().RunUntilIdle();
8508
Matt Menke9d5e2c92019-02-05 01:42:238509 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568510}
8511
[email protected]b4404c02009-04-10 16:38:528512// Make sure that we recycle a socket after a zero-length response.
8513// http://crbug.com/9880
bncd16676a2016-07-20 16:23:018514TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:428515 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:528516 request.method = "GET";
bncce36dca22015-04-21 22:11:238517 request.url = GURL(
8518 "http://www.example.org/csi?v=3&s=web&action=&"
8519 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
8520 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
8521 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:108522 request.traffic_annotation =
8523 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:528524
danakj1fd259a02016-04-16 03:17:098525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278526
[email protected]b4404c02009-04-10 16:38:528527 MockRead data_reads[] = {
8528 MockRead("HTTP/1.1 204 No Content\r\n"
8529 "Content-Length: 0\r\n"
8530 "Content-Type: text/html\r\n\r\n"),
8531 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068532 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:528533 };
8534
Ryan Sleevib8d7ea02018-05-07 20:01:018535 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078536 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:528537
mmenkecc2298e2015-12-07 18:20:188538 // Transaction must be created after the MockReads, so it's destroyed before
8539 // them.
bnc691fda62016-08-12 00:43:168540 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:188541
[email protected]49639fa2011-12-20 23:22:418542 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:528543
tfarina42834112016-09-22 13:38:208544 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:528546
8547 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018548 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528549
bnc691fda62016-08-12 00:43:168550 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528551 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:528552
wezca1070932016-05-26 20:30:528553 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:528554 std::string status_line = response->headers->GetStatusLine();
8555 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
8556
[email protected]90499482013-06-01 00:39:508557 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528558
8559 std::string response_data;
bnc691fda62016-08-12 00:43:168560 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018561 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528562 EXPECT_EQ("", response_data);
8563
8564 // Empty the current queue. This is necessary because idle sockets are
8565 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558566 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528567
8568 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508569 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528570}
8571
bncd16676a2016-07-20 16:23:018572TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:098573 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:228574 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:198575 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:228576 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:278577
[email protected]1c773ea12009-04-28 19:58:428578 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:518579 // Transaction 1: a GET request that succeeds. The socket is recycled
8580 // after use.
8581 request[0].method = "GET";
8582 request[0].url = GURL("http://www.google.com/");
8583 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108584 request[0].traffic_annotation =
8585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518586 // Transaction 2: a POST request. Reuses the socket kept alive from
8587 // transaction 1. The first attempts fails when writing the POST data.
8588 // This causes the transaction to retry with a new socket. The second
8589 // attempt succeeds.
8590 request[1].method = "POST";
8591 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:278592 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:518593 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108594 request[1].traffic_annotation =
8595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518596
danakj1fd259a02016-04-16 03:17:098597 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:518598
8599 // The first socket is used for transaction 1 and the first attempt of
8600 // transaction 2.
8601
8602 // The response of transaction 1.
8603 MockRead data_reads1[] = {
8604 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
8605 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068606 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518607 };
8608 // The mock write results of transaction 1 and the first attempt of
8609 // transaction 2.
8610 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:068611 MockWrite(SYNCHRONOUS, 64), // GET
8612 MockWrite(SYNCHRONOUS, 93), // POST
8613 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:518614 };
Ryan Sleevib8d7ea02018-05-07 20:01:018615 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:518616
8617 // The second socket is used for the second attempt of transaction 2.
8618
8619 // The response of transaction 2.
8620 MockRead data_reads2[] = {
8621 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
8622 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:068623 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518624 };
8625 // The mock write results of the second attempt of transaction 2.
8626 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:068627 MockWrite(SYNCHRONOUS, 93), // POST
8628 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:518629 };
Ryan Sleevib8d7ea02018-05-07 20:01:018630 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:518631
[email protected]bb88e1d32013-05-03 23:11:078632 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8633 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:518634
thestig9d3bb0c2015-01-24 00:49:518635 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:518636 "hello world", "welcome"
8637 };
8638
8639 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:168640 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:518641
[email protected]49639fa2011-12-20 23:22:418642 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:518643
tfarina42834112016-09-22 13:38:208644 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018645 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:518646
8647 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018648 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518649
bnc691fda62016-08-12 00:43:168650 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528651 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:518652
wezca1070932016-05-26 20:30:528653 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:518654 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8655
8656 std::string response_data;
bnc691fda62016-08-12 00:43:168657 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018658 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518659 EXPECT_EQ(kExpectedResponseData[i], response_data);
8660 }
8661}
[email protected]f9ee6b52008-11-08 06:46:238662
8663// Test the request-challenge-retry sequence for basic auth when there is
8664// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:168665// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:018666TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:428667 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238668 request.method = "GET";
bncce36dca22015-04-21 22:11:238669 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:418670 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108671 request.traffic_annotation =
8672 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:298673
danakj1fd259a02016-04-16 03:17:098674 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168675 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278676
[email protected]a97cca42009-08-14 01:00:298677 // The password contains an escaped character -- for this test to pass it
8678 // will need to be unescaped by HttpNetworkTransaction.
8679 EXPECT_EQ("b%40r", request.url.password());
8680
[email protected]f9ee6b52008-11-08 06:46:238681 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238682 MockWrite(
8683 "GET / HTTP/1.1\r\n"
8684 "Host: www.example.org\r\n"
8685 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238686 };
8687
8688 MockRead data_reads1[] = {
8689 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8690 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8691 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068692 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238693 };
8694
[email protected]2262e3a2012-05-22 16:08:168695 // After the challenge above, the transaction will be restarted using the
8696 // identity from the url (foo, b@r) to answer the challenge.
8697 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238698 MockWrite(
8699 "GET / HTTP/1.1\r\n"
8700 "Host: www.example.org\r\n"
8701 "Connection: keep-alive\r\n"
8702 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168703 };
8704
8705 MockRead data_reads2[] = {
8706 MockRead("HTTP/1.0 200 OK\r\n"),
8707 MockRead("Content-Length: 100\r\n\r\n"),
8708 MockRead(SYNCHRONOUS, OK),
8709 };
8710
Ryan Sleevib8d7ea02018-05-07 20:01:018711 StaticSocketDataProvider data1(data_reads1, data_writes1);
8712 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078713 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8714 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238715
[email protected]49639fa2011-12-20 23:22:418716 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208717 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018718 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238719 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018720 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168721 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168722
8723 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168724 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018725 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168726 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018727 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168728 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228729
bnc691fda62016-08-12 00:43:168730 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528731 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168732
8733 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:588734 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168735
8736 EXPECT_EQ(100, response->headers->GetContentLength());
8737
8738 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558739 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:168740}
8741
8742// Test the request-challenge-retry sequence for basic auth when there is an
8743// incorrect identity in the URL. The identity from the URL should be used only
8744// once.
bncd16676a2016-07-20 16:23:018745TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:168746 HttpRequestInfo request;
8747 request.method = "GET";
8748 // Note: the URL has a username:password in it. The password "baz" is
8749 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:238750 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:168751
8752 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108753 request.traffic_annotation =
8754 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:168755
danakj1fd259a02016-04-16 03:17:098756 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168757 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:168758
8759 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238760 MockWrite(
8761 "GET / HTTP/1.1\r\n"
8762 "Host: www.example.org\r\n"
8763 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168764 };
8765
8766 MockRead data_reads1[] = {
8767 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8768 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8769 MockRead("Content-Length: 10\r\n\r\n"),
8770 MockRead(SYNCHRONOUS, ERR_FAILED),
8771 };
8772
8773 // After the challenge above, the transaction will be restarted using the
8774 // identity from the url (foo, baz) to answer the challenge.
8775 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238776 MockWrite(
8777 "GET / HTTP/1.1\r\n"
8778 "Host: www.example.org\r\n"
8779 "Connection: keep-alive\r\n"
8780 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168781 };
8782
8783 MockRead data_reads2[] = {
8784 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8785 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8786 MockRead("Content-Length: 10\r\n\r\n"),
8787 MockRead(SYNCHRONOUS, ERR_FAILED),
8788 };
8789
8790 // After the challenge above, the transaction will be restarted using the
8791 // identity supplied by the user (foo, bar) to answer the challenge.
8792 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238793 MockWrite(
8794 "GET / HTTP/1.1\r\n"
8795 "Host: www.example.org\r\n"
8796 "Connection: keep-alive\r\n"
8797 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168798 };
8799
8800 MockRead data_reads3[] = {
8801 MockRead("HTTP/1.0 200 OK\r\n"),
8802 MockRead("Content-Length: 100\r\n\r\n"),
8803 MockRead(SYNCHRONOUS, OK),
8804 };
8805
Ryan Sleevib8d7ea02018-05-07 20:01:018806 StaticSocketDataProvider data1(data_reads1, data_writes1);
8807 StaticSocketDataProvider data2(data_reads2, data_writes2);
8808 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8810 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8811 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:168812
8813 TestCompletionCallback callback1;
8814
tfarina42834112016-09-22 13:38:208815 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018816 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168817
8818 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018819 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:168820
bnc691fda62016-08-12 00:43:168821 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168822 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168823 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018824 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168825 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018826 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168827 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168828
bnc691fda62016-08-12 00:43:168829 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528830 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588831 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:168832
8833 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168834 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018835 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168836 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018837 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168838 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168839
bnc691fda62016-08-12 00:43:168840 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528841 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168842
8843 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588844 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168845
8846 EXPECT_EQ(100, response->headers->GetContentLength());
8847
[email protected]ea9dc9a2009-09-05 00:43:328848 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558849 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:328850}
8851
[email protected]2217aa22013-10-11 03:03:548852
8853// Test the request-challenge-retry sequence for basic auth when there is a
8854// correct identity in the URL, but its use is being suppressed. The identity
8855// from the URL should never be used.
bncd16676a2016-07-20 16:23:018856TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:548857 HttpRequestInfo request;
8858 request.method = "GET";
bncce36dca22015-04-21 22:11:238859 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:548860 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:108861 request.traffic_annotation =
8862 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548863
danakj1fd259a02016-04-16 03:17:098864 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168865 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:548866
8867 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238868 MockWrite(
8869 "GET / HTTP/1.1\r\n"
8870 "Host: www.example.org\r\n"
8871 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548872 };
8873
8874 MockRead data_reads1[] = {
8875 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8876 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8877 MockRead("Content-Length: 10\r\n\r\n"),
8878 MockRead(SYNCHRONOUS, ERR_FAILED),
8879 };
8880
8881 // After the challenge above, the transaction will be restarted using the
8882 // identity supplied by the user, not the one in the URL, to answer the
8883 // challenge.
8884 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238885 MockWrite(
8886 "GET / HTTP/1.1\r\n"
8887 "Host: www.example.org\r\n"
8888 "Connection: keep-alive\r\n"
8889 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548890 };
8891
8892 MockRead data_reads3[] = {
8893 MockRead("HTTP/1.0 200 OK\r\n"),
8894 MockRead("Content-Length: 100\r\n\r\n"),
8895 MockRead(SYNCHRONOUS, OK),
8896 };
8897
Ryan Sleevib8d7ea02018-05-07 20:01:018898 StaticSocketDataProvider data1(data_reads1, data_writes1);
8899 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:548900 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8901 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8902
8903 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208904 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018905 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548906 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018907 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168908 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548909
bnc691fda62016-08-12 00:43:168910 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528911 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588912 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:548913
8914 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168915 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018916 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548917 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018918 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168919 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548920
bnc691fda62016-08-12 00:43:168921 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528922 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:548923
8924 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588925 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:548926 EXPECT_EQ(100, response->headers->GetContentLength());
8927
8928 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558929 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:548930}
8931
[email protected]f9ee6b52008-11-08 06:46:238932// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:018933TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:098934 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:238935
8936 // Transaction 1: authenticate (foo, bar) on MyRealm1
8937 {
[email protected]1c773ea12009-04-28 19:58:428938 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238939 request.method = "GET";
bncce36dca22015-04-21 22:11:238940 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:108941 request.traffic_annotation =
8942 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238943
bnc691fda62016-08-12 00:43:168944 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278945
[email protected]f9ee6b52008-11-08 06:46:238946 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238947 MockWrite(
8948 "GET /x/y/z HTTP/1.1\r\n"
8949 "Host: www.example.org\r\n"
8950 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238951 };
8952
8953 MockRead data_reads1[] = {
8954 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8955 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8956 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068957 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238958 };
8959
8960 // Resend with authorization (username=foo, password=bar)
8961 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238962 MockWrite(
8963 "GET /x/y/z HTTP/1.1\r\n"
8964 "Host: www.example.org\r\n"
8965 "Connection: keep-alive\r\n"
8966 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238967 };
8968
8969 // Sever accepts the authorization.
8970 MockRead data_reads2[] = {
8971 MockRead("HTTP/1.0 200 OK\r\n"),
8972 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068973 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238974 };
8975
Ryan Sleevib8d7ea02018-05-07 20:01:018976 StaticSocketDataProvider data1(data_reads1, data_writes1);
8977 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078978 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8979 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238980
[email protected]49639fa2011-12-20 23:22:418981 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238982
tfarina42834112016-09-22 13:38:208983 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018984 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238985
8986 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018987 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238988
bnc691fda62016-08-12 00:43:168989 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528990 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588991 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:238992
[email protected]49639fa2011-12-20 23:22:418993 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238994
bnc691fda62016-08-12 00:43:168995 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
8996 callback2.callback());
robpercival214763f2016-07-01 23:27:018997 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238998
8999 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019000 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239001
bnc691fda62016-08-12 00:43:169002 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529003 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589004 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239005 EXPECT_EQ(100, response->headers->GetContentLength());
9006 }
9007
9008 // ------------------------------------------------------------------------
9009
9010 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
9011 {
[email protected]1c773ea12009-04-28 19:58:429012 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239013 request.method = "GET";
9014 // Note that Transaction 1 was at /x/y/z, so this is in the same
9015 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:239016 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109017 request.traffic_annotation =
9018 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239019
bnc691fda62016-08-12 00:43:169020 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279021
[email protected]f9ee6b52008-11-08 06:46:239022 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239023 MockWrite(
9024 "GET /x/y/a/b HTTP/1.1\r\n"
9025 "Host: www.example.org\r\n"
9026 "Connection: keep-alive\r\n"
9027 // Send preemptive authorization for MyRealm1
9028 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239029 };
9030
9031 // The server didn't like the preemptive authorization, and
9032 // challenges us for a different realm (MyRealm2).
9033 MockRead data_reads1[] = {
9034 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9035 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
9036 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069037 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239038 };
9039
9040 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
9041 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239042 MockWrite(
9043 "GET /x/y/a/b HTTP/1.1\r\n"
9044 "Host: www.example.org\r\n"
9045 "Connection: keep-alive\r\n"
9046 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239047 };
9048
9049 // Sever accepts the authorization.
9050 MockRead data_reads2[] = {
9051 MockRead("HTTP/1.0 200 OK\r\n"),
9052 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069053 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239054 };
9055
Ryan Sleevib8d7ea02018-05-07 20:01:019056 StaticSocketDataProvider data1(data_reads1, data_writes1);
9057 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079058 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9059 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239060
[email protected]49639fa2011-12-20 23:22:419061 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239062
tfarina42834112016-09-22 13:38:209063 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019064 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239065
9066 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019067 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239068
bnc691fda62016-08-12 00:43:169069 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529070 ASSERT_TRUE(response);
9071 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:049072 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:439073 EXPECT_EQ("http://www.example.org",
9074 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049075 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:199076 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:239077
[email protected]49639fa2011-12-20 23:22:419078 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:239079
bnc691fda62016-08-12 00:43:169080 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
9081 callback2.callback());
robpercival214763f2016-07-01 23:27:019082 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239083
9084 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019085 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239086
bnc691fda62016-08-12 00:43:169087 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529088 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589089 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239090 EXPECT_EQ(100, response->headers->GetContentLength());
9091 }
9092
9093 // ------------------------------------------------------------------------
9094
9095 // Transaction 3: Resend a request in MyRealm's protection space --
9096 // succeed with preemptive authorization.
9097 {
[email protected]1c773ea12009-04-28 19:58:429098 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239099 request.method = "GET";
bncce36dca22015-04-21 22:11:239100 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:109101 request.traffic_annotation =
9102 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239103
bnc691fda62016-08-12 00:43:169104 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279105
[email protected]f9ee6b52008-11-08 06:46:239106 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239107 MockWrite(
9108 "GET /x/y/z2 HTTP/1.1\r\n"
9109 "Host: www.example.org\r\n"
9110 "Connection: keep-alive\r\n"
9111 // The authorization for MyRealm1 gets sent preemptively
9112 // (since the url is in the same protection space)
9113 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239114 };
9115
9116 // Sever accepts the preemptive authorization
9117 MockRead data_reads1[] = {
9118 MockRead("HTTP/1.0 200 OK\r\n"),
9119 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069120 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239121 };
9122
Ryan Sleevib8d7ea02018-05-07 20:01:019123 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079124 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:239125
[email protected]49639fa2011-12-20 23:22:419126 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239127
tfarina42834112016-09-22 13:38:209128 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019129 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239130
9131 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019132 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239133
bnc691fda62016-08-12 00:43:169134 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529135 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:239136
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
9141 // ------------------------------------------------------------------------
9142
9143 // Transaction 4: request another URL in MyRealm (however the
9144 // url is not known to belong to the protection space, so no pre-auth).
9145 {
[email protected]1c773ea12009-04-28 19:58:429146 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239147 request.method = "GET";
bncce36dca22015-04-21 22:11:239148 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:109149 request.traffic_annotation =
9150 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239151
bnc691fda62016-08-12 00:43:169152 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279153
[email protected]f9ee6b52008-11-08 06:46:239154 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239155 MockWrite(
9156 "GET /x/1 HTTP/1.1\r\n"
9157 "Host: www.example.org\r\n"
9158 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239159 };
9160
9161 MockRead data_reads1[] = {
9162 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9163 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9164 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069165 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239166 };
9167
9168 // Resend with authorization from MyRealm's cache.
9169 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239170 MockWrite(
9171 "GET /x/1 HTTP/1.1\r\n"
9172 "Host: www.example.org\r\n"
9173 "Connection: keep-alive\r\n"
9174 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239175 };
9176
9177 // Sever accepts the authorization.
9178 MockRead data_reads2[] = {
9179 MockRead("HTTP/1.0 200 OK\r\n"),
9180 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069181 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239182 };
9183
Ryan Sleevib8d7ea02018-05-07 20:01:019184 StaticSocketDataProvider data1(data_reads1, data_writes1);
9185 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079186 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9187 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239188
[email protected]49639fa2011-12-20 23:22:419189 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239190
tfarina42834112016-09-22 13:38:209191 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019192 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239193
9194 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019195 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239196
bnc691fda62016-08-12 00:43:169197 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419198 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169199 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019200 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229201 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019202 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169203 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229204
bnc691fda62016-08-12 00:43:169205 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529206 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589207 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239208 EXPECT_EQ(100, response->headers->GetContentLength());
9209 }
9210
9211 // ------------------------------------------------------------------------
9212
9213 // Transaction 5: request a URL in MyRealm, but the server rejects the
9214 // cached identity. Should invalidate and re-prompt.
9215 {
[email protected]1c773ea12009-04-28 19:58:429216 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239217 request.method = "GET";
bncce36dca22015-04-21 22:11:239218 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:109219 request.traffic_annotation =
9220 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239221
bnc691fda62016-08-12 00:43:169222 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279223
[email protected]f9ee6b52008-11-08 06:46:239224 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239225 MockWrite(
9226 "GET /p/q/t HTTP/1.1\r\n"
9227 "Host: www.example.org\r\n"
9228 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239229 };
9230
9231 MockRead data_reads1[] = {
9232 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9233 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9234 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069235 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239236 };
9237
9238 // Resend with authorization from cache for MyRealm.
9239 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239240 MockWrite(
9241 "GET /p/q/t HTTP/1.1\r\n"
9242 "Host: www.example.org\r\n"
9243 "Connection: keep-alive\r\n"
9244 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239245 };
9246
9247 // Sever rejects the authorization.
9248 MockRead data_reads2[] = {
9249 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9250 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9251 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069252 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239253 };
9254
9255 // At this point we should prompt for new credentials for MyRealm.
9256 // Restart with username=foo3, password=foo4.
9257 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239258 MockWrite(
9259 "GET /p/q/t HTTP/1.1\r\n"
9260 "Host: www.example.org\r\n"
9261 "Connection: keep-alive\r\n"
9262 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239263 };
9264
9265 // Sever accepts the authorization.
9266 MockRead data_reads3[] = {
9267 MockRead("HTTP/1.0 200 OK\r\n"),
9268 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069269 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239270 };
9271
Ryan Sleevib8d7ea02018-05-07 20:01:019272 StaticSocketDataProvider data1(data_reads1, data_writes1);
9273 StaticSocketDataProvider data2(data_reads2, data_writes2);
9274 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079275 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9276 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9277 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239278
[email protected]49639fa2011-12-20 23:22:419279 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239280
tfarina42834112016-09-22 13:38:209281 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019282 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239283
9284 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019285 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239286
bnc691fda62016-08-12 00:43:169287 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419288 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169289 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019290 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229291 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019292 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169293 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229294
bnc691fda62016-08-12 00:43:169295 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529296 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589297 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239298
[email protected]49639fa2011-12-20 23:22:419299 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239300
bnc691fda62016-08-12 00:43:169301 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9302 callback3.callback());
robpercival214763f2016-07-01 23:27:019303 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239304
[email protected]0757e7702009-03-27 04:00:229305 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019306 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239307
bnc691fda62016-08-12 00:43:169308 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529309 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589310 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239311 EXPECT_EQ(100, response->headers->GetContentLength());
9312 }
9313}
[email protected]89ceba9a2009-03-21 03:46:069314
[email protected]3c32c5f2010-05-18 15:18:129315// Tests that nonce count increments when multiple auth attempts
9316// are started with the same nonce.
bncd16676a2016-07-20 16:23:019317TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449318 HttpAuthHandlerDigest::Factory* digest_factory =
9319 new HttpAuthHandlerDigest::Factory();
9320 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
9321 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
9322 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:079323 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:099324 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:129325
9326 // Transaction 1: authenticate (foo, bar) on MyRealm1
9327 {
[email protected]3c32c5f2010-05-18 15:18:129328 HttpRequestInfo request;
9329 request.method = "GET";
bncce36dca22015-04-21 22:11:239330 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109331 request.traffic_annotation =
9332 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129333
bnc691fda62016-08-12 00:43:169334 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279335
[email protected]3c32c5f2010-05-18 15:18:129336 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239337 MockWrite(
9338 "GET /x/y/z HTTP/1.1\r\n"
9339 "Host: www.example.org\r\n"
9340 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129341 };
9342
9343 MockRead data_reads1[] = {
9344 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9345 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
9346 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069347 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129348 };
9349
9350 // Resend with authorization (username=foo, password=bar)
9351 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239352 MockWrite(
9353 "GET /x/y/z HTTP/1.1\r\n"
9354 "Host: www.example.org\r\n"
9355 "Connection: keep-alive\r\n"
9356 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9357 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
9358 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
9359 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129360 };
9361
9362 // Sever accepts the authorization.
9363 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:089364 MockRead("HTTP/1.0 200 OK\r\n"),
9365 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129366 };
9367
Ryan Sleevib8d7ea02018-05-07 20:01:019368 StaticSocketDataProvider data1(data_reads1, data_writes1);
9369 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079370 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9371 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:129372
[email protected]49639fa2011-12-20 23:22:419373 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129374
tfarina42834112016-09-22 13:38:209375 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019376 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129377
9378 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019379 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129380
bnc691fda62016-08-12 00:43:169381 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529382 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589383 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:129384
[email protected]49639fa2011-12-20 23:22:419385 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:129386
bnc691fda62016-08-12 00:43:169387 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9388 callback2.callback());
robpercival214763f2016-07-01 23:27:019389 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129390
9391 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019392 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129393
bnc691fda62016-08-12 00:43:169394 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529395 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589396 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129397 }
9398
9399 // ------------------------------------------------------------------------
9400
9401 // Transaction 2: Request another resource in digestive's protection space.
9402 // This will preemptively add an Authorization header which should have an
9403 // "nc" value of 2 (as compared to 1 in the first use.
9404 {
[email protected]3c32c5f2010-05-18 15:18:129405 HttpRequestInfo request;
9406 request.method = "GET";
9407 // Note that Transaction 1 was at /x/y/z, so this is in the same
9408 // protection space as digest.
bncce36dca22015-04-21 22:11:239409 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109410 request.traffic_annotation =
9411 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129412
bnc691fda62016-08-12 00:43:169413 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279414
[email protected]3c32c5f2010-05-18 15:18:129415 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239416 MockWrite(
9417 "GET /x/y/a/b HTTP/1.1\r\n"
9418 "Host: www.example.org\r\n"
9419 "Connection: keep-alive\r\n"
9420 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9421 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
9422 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
9423 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129424 };
9425
9426 // Sever accepts the authorization.
9427 MockRead data_reads1[] = {
9428 MockRead("HTTP/1.0 200 OK\r\n"),
9429 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069430 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129431 };
9432
Ryan Sleevib8d7ea02018-05-07 20:01:019433 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079434 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:129435
[email protected]49639fa2011-12-20 23:22:419436 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129437
tfarina42834112016-09-22 13:38:209438 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019439 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129440
9441 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019442 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129443
bnc691fda62016-08-12 00:43:169444 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529445 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589446 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129447 }
9448}
9449
[email protected]89ceba9a2009-03-21 03:46:069450// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:019451TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:069452 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:099453 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169454 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:069455
9456 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:449457 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:169458 trans.read_buf_len_ = 15;
9459 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:069460
9461 // Setup state in response_
bnc691fda62016-08-12 00:43:169462 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:589463 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:089464 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:579465 response->response_time = base::Time::Now();
9466 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:069467
9468 { // Setup state for response_.vary_data
9469 HttpRequestInfo request;
9470 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
9471 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:279472 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:439473 request.extra_headers.SetHeader("Foo", "1");
9474 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:509475 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:069476 }
9477
9478 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:169479 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:069480
9481 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:169482 EXPECT_FALSE(trans.read_buf_);
9483 EXPECT_EQ(0, trans.read_buf_len_);
9484 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:589485 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:529486 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:049487 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:089488 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:579489 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:069490}
9491
[email protected]bacff652009-03-31 17:50:339492// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:019493TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:339494 HttpRequestInfo request;
9495 request.method = "GET";
bncce36dca22015-04-21 22:11:239496 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109497 request.traffic_annotation =
9498 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339499
danakj1fd259a02016-04-16 03:17:099500 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169501 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279502
[email protected]bacff652009-03-31 17:50:339503 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239504 MockWrite(
9505 "GET / HTTP/1.1\r\n"
9506 "Host: www.example.org\r\n"
9507 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339508 };
9509
9510 MockRead data_reads[] = {
9511 MockRead("HTTP/1.0 200 OK\r\n"),
9512 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9513 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069514 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339515 };
9516
[email protected]5ecc992a42009-11-11 01:41:599517 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:019518 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069519 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9520 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339521
[email protected]bb88e1d32013-05-03 23:11:079522 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9523 session_deps_.socket_factory->AddSocketDataProvider(&data);
9524 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9525 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339526
[email protected]49639fa2011-12-20 23:22:419527 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339528
tfarina42834112016-09-22 13:38:209529 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019530 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339531
9532 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019533 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339534
bnc691fda62016-08-12 00:43:169535 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019536 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339537
9538 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019539 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339540
bnc691fda62016-08-12 00:43:169541 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339542
wezca1070932016-05-26 20:30:529543 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339544 EXPECT_EQ(100, response->headers->GetContentLength());
9545}
9546
9547// Test HTTPS connections to a site with a bad certificate, going through a
9548// proxy
bncd16676a2016-07-20 16:23:019549TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499550 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9551 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339552
9553 HttpRequestInfo request;
9554 request.method = "GET";
bncce36dca22015-04-21 22:11:239555 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109556 request.traffic_annotation =
9557 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339558
9559 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:179560 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9561 "Host: www.example.org:443\r\n"
9562 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339563 };
9564
9565 MockRead proxy_reads[] = {
9566 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069567 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:339568 };
9569
9570 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179571 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9572 "Host: www.example.org:443\r\n"
9573 "Proxy-Connection: keep-alive\r\n\r\n"),
9574 MockWrite("GET / HTTP/1.1\r\n"
9575 "Host: www.example.org\r\n"
9576 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339577 };
9578
9579 MockRead data_reads[] = {
9580 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9581 MockRead("HTTP/1.0 200 OK\r\n"),
9582 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9583 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069584 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339585 };
9586
Ryan Sleevib8d7ea02018-05-07 20:01:019587 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
9588 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069589 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9590 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339591
[email protected]bb88e1d32013-05-03 23:11:079592 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9593 session_deps_.socket_factory->AddSocketDataProvider(&data);
9594 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9595 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339596
[email protected]49639fa2011-12-20 23:22:419597 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339598
9599 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:079600 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:339601
danakj1fd259a02016-04-16 03:17:099602 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169603 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:339604
tfarina42834112016-09-22 13:38:209605 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019606 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339607
9608 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019609 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339610
bnc691fda62016-08-12 00:43:169611 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019612 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339613
9614 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019615 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339616
bnc691fda62016-08-12 00:43:169617 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339618
wezca1070932016-05-26 20:30:529619 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339620 EXPECT_EQ(100, response->headers->GetContentLength());
9621 }
9622}
9623
[email protected]2df19bb2010-08-25 20:13:469624
9625// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:019626TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599627 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499628 ProxyResolutionService::CreateFixedFromPacResult(
9629 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519630 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079631 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:469632
9633 HttpRequestInfo request;
9634 request.method = "GET";
bncce36dca22015-04-21 22:11:239635 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109636 request.traffic_annotation =
9637 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:469638
9639 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179640 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9641 "Host: www.example.org:443\r\n"
9642 "Proxy-Connection: keep-alive\r\n\r\n"),
9643 MockWrite("GET / HTTP/1.1\r\n"
9644 "Host: www.example.org\r\n"
9645 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:469646 };
9647
9648 MockRead data_reads[] = {
9649 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9650 MockRead("HTTP/1.1 200 OK\r\n"),
9651 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9652 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069653 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:469654 };
9655
Ryan Sleevib8d7ea02018-05-07 20:01:019656 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069657 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9658 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:469659
[email protected]bb88e1d32013-05-03 23:11:079660 session_deps_.socket_factory->AddSocketDataProvider(&data);
9661 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9662 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:469663
[email protected]49639fa2011-12-20 23:22:419664 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:469665
danakj1fd259a02016-04-16 03:17:099666 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169667 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:469668
tfarina42834112016-09-22 13:38:209669 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019670 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:469671
9672 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019673 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169674 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:469675
wezca1070932016-05-26 20:30:529676 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:469677
tbansal2ecbbc72016-10-06 17:15:479678 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:469679 EXPECT_TRUE(response->headers->IsKeepAlive());
9680 EXPECT_EQ(200, response->headers->response_code());
9681 EXPECT_EQ(100, response->headers->GetContentLength());
9682 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:209683
9684 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:169685 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:209686 TestLoadTimingNotReusedWithPac(load_timing_info,
9687 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:469688}
9689
Eric Roman695a7872019-04-16 21:53:299690// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:019691TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599692 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499693 ProxyResolutionService::CreateFixedFromPacResult(
9694 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519695 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079696 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:299697
Matt Menkeecfecfc72019-02-05 19:15:289698 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9699 session_deps_.host_resolver->set_ondemand_mode(true);
9700
[email protected]511f6f52010-12-17 03:58:299701 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:129702 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:299703 request.method = "GET";
bncce36dca22015-04-21 22:11:239704 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109705 request.traffic_annotation =
9706 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299707
9708 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:289709 MockWrite(ASYNC, 0,
9710 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:179711 "Host: www.example.org:443\r\n"
9712 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299713 };
9714
9715 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289716 // Pause on first read.
9717 MockRead(ASYNC, ERR_IO_PENDING, 1),
9718 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
9719 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
9720 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299721 };
9722
Matt Menkeecfecfc72019-02-05 19:15:289723 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069724 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299725
[email protected]bb88e1d32013-05-03 23:11:079726 session_deps_.socket_factory->AddSocketDataProvider(&data);
9727 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299728
[email protected]49639fa2011-12-20 23:22:419729 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299730
danakj1fd259a02016-04-16 03:17:099731 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169732 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299733
tfarina42834112016-09-22 13:38:209734 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019735 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289736 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
9737
9738 // Host resolution takes |kTimeIncrement|.
9739 FastForwardBy(kTimeIncrement);
9740 // Resolving the current request with |ResolveNow| will cause the pending
9741 // request to instantly complete, and the async connect will start as well.
9742 session_deps_.host_resolver->ResolveOnlyRequestNow();
9743
9744 // Connecting takes |kTimeIncrement|.
9745 FastForwardBy(kTimeIncrement);
9746 data.RunUntilPaused();
9747
9748 // The server takes |kTimeIncrement| to respond.
9749 FastForwardBy(kTimeIncrement);
9750 data.Resume();
[email protected]511f6f52010-12-17 03:58:299751
9752 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599753 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299754}
9755
Eric Roman74103c72019-02-21 00:23:129756// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
9757TEST_F(HttpNetworkTransactionTest,
9758 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
9759 base::HistogramTester histograms;
9760 session_deps_.proxy_resolution_service =
9761 ProxyResolutionService::CreateFixedFromPacResult(
9762 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9763 TestNetLog net_log;
9764 session_deps_.net_log = &net_log;
9765
9766 HttpRequestInfo request;
9767 request.method = "GET";
9768 request.url = GURL("https://www.example.org/");
9769 request.traffic_annotation =
9770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9771
9772 MockWrite data_writes[] = {
9773 MockWrite(ASYNC, 0,
9774 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9775 "Host: www.example.org:443\r\n"
9776 "Proxy-Connection: keep-alive\r\n\r\n"),
9777 };
9778
9779 MockRead data_reads[] = {
9780 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9781 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9782 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9783 };
9784
9785 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9786 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9787
9788 session_deps_.socket_factory->AddSocketDataProvider(&data);
9789 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9790
9791 TestCompletionCallback callback;
9792
9793 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9795
9796 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9797 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9798
9799 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599800 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129801}
9802
9803// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
9804// request for main frames.
9805TEST_F(HttpNetworkTransactionTest,
9806 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
9807 base::HistogramTester histograms;
9808 session_deps_.proxy_resolution_service =
9809 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
9810 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9811 TestNetLog net_log;
9812 session_deps_.net_log = &net_log;
9813
9814 HttpRequestInfo request;
9815 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
9816 request.method = "GET";
9817 request.url = GURL("https://www.example.org/");
9818 request.traffic_annotation =
9819 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9820
9821 MockWrite data_writes[] = {
9822 MockWrite(ASYNC, 0,
9823 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9824 "Host: www.example.org:443\r\n"
9825 "Proxy-Connection: keep-alive\r\n\r\n"),
9826 };
9827
9828 MockRead data_reads[] = {
9829 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9830 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9831 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9832 };
9833
9834 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9835 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9836
9837 session_deps_.socket_factory->AddSocketDataProvider(&data);
9838 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9839
9840 TestCompletionCallback callback;
9841
9842 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9843 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9844
9845 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9846 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9847
9848 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599849 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129850}
9851
Eric Roman695a7872019-04-16 21:53:299852// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:129853// frames.
bncd16676a2016-07-20 16:23:019854TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:129855 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:499856 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9857 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:289858 TestNetLog net_log;
9859 session_deps_.net_log = &net_log;
9860
Matt Menkeecfecfc72019-02-05 19:15:289861 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9862 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:299863
9864 HttpRequestInfo request;
9865 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:129866 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:239867 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109868 request.traffic_annotation =
9869 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299870
Ryan Hamilton0239aac2018-05-19 00:03:139871 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049872 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9873 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139874 spdy::SpdySerializedFrame goaway(
9875 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299876 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419877 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:289878 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:299879 };
9880
9881 static const char* const kExtraHeaders[] = {
9882 "location",
9883 "http://login.example.com/",
9884 };
Ryan Hamilton0239aac2018-05-19 00:03:139885 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249886 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:299887 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289888 // Pause on first read.
9889 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
9890 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299891 };
9892
Matt Menkeecfecfc72019-02-05 19:15:289893 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069894 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369895 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299896
[email protected]bb88e1d32013-05-03 23:11:079897 session_deps_.socket_factory->AddSocketDataProvider(&data);
9898 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299899
[email protected]49639fa2011-12-20 23:22:419900 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299901
danakj1fd259a02016-04-16 03:17:099902 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169903 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299904
tfarina42834112016-09-22 13:38:209905 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019906 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289907 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:299908
Matt Menkeecfecfc72019-02-05 19:15:289909 // Host resolution takes |kTimeIncrement|.
9910 FastForwardBy(kTimeIncrement);
9911 // Resolving the current request with |ResolveNow| will cause the pending
9912 // request to instantly complete, and the async connect will start as well.
9913 session_deps_.host_resolver->ResolveOnlyRequestNow();
9914
9915 // Connecting takes |kTimeIncrement|.
9916 FastForwardBy(kTimeIncrement);
9917 data.RunUntilPaused();
9918
9919 FastForwardBy(kTimeIncrement);
9920 data.Resume();
[email protected]511f6f52010-12-17 03:58:299921 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599922 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299923}
9924
[email protected]4eddbc732012-08-09 05:40:179925// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019926TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499927 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9928 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299929
9930 HttpRequestInfo request;
9931 request.method = "GET";
bncce36dca22015-04-21 22:11:239932 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109933 request.traffic_annotation =
9934 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299935
9936 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179937 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9938 "Host: www.example.org:443\r\n"
9939 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299940 };
9941
9942 MockRead data_reads[] = {
9943 MockRead("HTTP/1.1 404 Not Found\r\n"),
9944 MockRead("Content-Length: 23\r\n\r\n"),
9945 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:069946 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:299947 };
9948
Ryan Sleevib8d7ea02018-05-07 20:01:019949 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069950 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299951
[email protected]bb88e1d32013-05-03 23:11:079952 session_deps_.socket_factory->AddSocketDataProvider(&data);
9953 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299954
[email protected]49639fa2011-12-20 23:22:419955 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299956
danakj1fd259a02016-04-16 03:17:099957 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169958 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299959
tfarina42834112016-09-22 13:38:209960 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019961 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299962
9963 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019964 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299965
ttuttle960fcbf2016-04-19 13:26:329966 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299967}
9968
[email protected]4eddbc732012-08-09 05:40:179969// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019970TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499971 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9972 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299973
9974 HttpRequestInfo request;
9975 request.method = "GET";
bncce36dca22015-04-21 22:11:239976 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109977 request.traffic_annotation =
9978 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299979
Ryan Hamilton0239aac2018-05-19 00:03:139980 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049981 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9982 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139983 spdy::SpdySerializedFrame rst(
9984 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299985 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419986 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:299987 };
9988
9989 static const char* const kExtraHeaders[] = {
9990 "location",
9991 "http://login.example.com/",
9992 };
Ryan Hamilton0239aac2018-05-19 00:03:139993 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249994 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:139995 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:199996 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:299997 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:419998 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:139999 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:2910000 };
10001
Ryan Sleevib8d7ea02018-05-07 20:01:0110002 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:0610003 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:3610004 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:2910005
[email protected]bb88e1d32013-05-03 23:11:0710006 session_deps_.socket_factory->AddSocketDataProvider(&data);
10007 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:2910008
[email protected]49639fa2011-12-20 23:22:4110009 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:2910010
danakj1fd259a02016-04-16 03:17:0910011 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610012 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:2910013
tfarina42834112016-09-22 13:38:2010014 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110015 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:2910016
10017 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110018 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:2910019
ttuttle960fcbf2016-04-19 13:26:3210020 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:2910021}
10022
[email protected]0c5fb722012-02-28 11:50:3510023// Test the request-challenge-retry sequence for basic auth, through
10024// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:0110025TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:3510026 HttpRequestInfo request;
10027 request.method = "GET";
bncce36dca22015-04-21 22:11:2310028 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:3510029 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:2910030 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:1010031 request.traffic_annotation =
10032 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:3510033
10034 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5910035 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910036 ProxyResolutionService::CreateFixedFromPacResult(
10037 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110038 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710039 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0910040 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:3510041
10042 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:1310043 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410044 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10045 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:1310046 spdy::SpdySerializedFrame rst(
10047 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:3810048 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:3510049
bnc691fda62016-08-12 00:43:1610050 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:3510051 // be issuing -- the final header line contains the credentials.
10052 const char* const kAuthCredentials[] = {
10053 "proxy-authorization", "Basic Zm9vOmJhcg==",
10054 };
Ryan Hamilton0239aac2018-05-19 00:03:1310055 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:0410056 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
10057 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:2310058 HostPortPair("www.example.org", 443)));
10059 // fetch https://www.example.org/ via HTTP
10060 const char get[] =
10061 "GET / HTTP/1.1\r\n"
10062 "Host: www.example.org\r\n"
10063 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:1310064 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:1910065 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:3510066
10067 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110068 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
10069 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:3510070 };
10071
10072 // The proxy responds to the connect with a 407, using a persistent
10073 // connection.
thestig9d3bb0c2015-01-24 00:49:5110074 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:3510075 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:3510076 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
10077 };
Ryan Hamilton0239aac2018-05-19 00:03:1310078 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:2410079 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:3510080
Ryan Hamilton0239aac2018-05-19 00:03:1310081 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:3510082 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:3510083 const char resp[] = "HTTP/1.1 200 OK\r\n"
10084 "Content-Length: 5\r\n\r\n";
10085
Ryan Hamilton0239aac2018-05-19 00:03:1310086 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:1910087 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:1310088 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:1910089 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:3510090 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110091 CreateMockRead(conn_auth_resp, 1, ASYNC),
10092 CreateMockRead(conn_resp, 4, ASYNC),
10093 CreateMockRead(wrapped_get_resp, 6, ASYNC),
10094 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:1310095 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:3510096 };
10097
Ryan Sleevib8d7ea02018-05-07 20:01:0110098 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710099 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:3510100 // Negotiate SPDY to the proxy
10101 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610102 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710103 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:3510104 // Vanilla SSL to the server
10105 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710106 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:3510107
10108 TestCompletionCallback callback1;
10109
bnc87dcefc2017-05-25 12:47:5810110 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910111 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:3510112
10113 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110114 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510115
10116 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0110117 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5410118 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:3510119 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0010120 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10121 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510122 ExpectLogContainsSomewhere(
10123 entries, pos,
mikecirone8b85c432016-09-08 19:11:0010124 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10125 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:3510126
10127 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210128 ASSERT_TRUE(response);
10129 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:3510130 EXPECT_EQ(407, response->headers->response_code());
10131 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:5810132 EXPECT_TRUE(response->auth_challenge.has_value());
10133 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:3510134
10135 TestCompletionCallback callback2;
10136
10137 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
10138 callback2.callback());
robpercival214763f2016-07-01 23:27:0110139 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:3510140
10141 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0110142 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:3510143
10144 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210145 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:3510146
10147 EXPECT_TRUE(response->headers->IsKeepAlive());
10148 EXPECT_EQ(200, response->headers->response_code());
10149 EXPECT_EQ(5, response->headers->GetContentLength());
10150 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10151
10152 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810153 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510154
[email protected]029c83b62013-01-24 05:28:2010155 LoadTimingInfo load_timing_info;
10156 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10157 TestLoadTimingNotReusedWithPac(load_timing_info,
10158 CONNECT_TIMING_HAS_SSL_TIMES);
10159
[email protected]0c5fb722012-02-28 11:50:3510160 trans.reset();
10161 session->CloseAllConnections();
10162}
10163
[email protected]7c6f7ba2012-04-03 04:09:2910164// Test that an explicitly trusted SPDY proxy can push a resource from an
10165// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110166TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510167 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910168 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510169 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10170 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910171 HttpRequestInfo request;
10172 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:1010173 request.traffic_annotation =
10174 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910175
[email protected]7c6f7ba2012-04-03 04:09:2910176 request.method = "GET";
bncce36dca22015-04-21 22:11:2310177 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910178 push_request.method = "GET";
10179 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1010180 push_request.traffic_annotation =
10181 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910182
tbansal28e68f82016-02-04 02:56:1510183 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910184 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910185 ProxyResolutionService::CreateFixedFromPacResult(
10186 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110187 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710188 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010189
Eric Roman3d8546a2018-09-10 17:00:5210190 session_deps_.proxy_resolution_service->SetProxyDelegate(
10191 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010192
danakj1fd259a02016-04-16 03:17:0910193 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910194
Ryan Hamilton0239aac2018-05-19 00:03:1310195 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510196 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310197 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510198 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910199
10200 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110201 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510202 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910203 };
10204
Ryan Hamilton0239aac2018-05-19 00:03:1310205 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510206 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610207
Ryan Hamilton0239aac2018-05-19 00:03:1310208 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510209 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910210
Ryan Hamilton0239aac2018-05-19 00:03:1310211 spdy::SpdySerializedFrame stream1_body(
10212 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910213
Ryan Hamilton0239aac2018-05-19 00:03:1310214 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910215 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910216
10217 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610218 CreateMockRead(stream2_syn, 1, ASYNC),
10219 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510220 CreateMockRead(stream1_body, 4, ASYNC),
10221 CreateMockRead(stream2_body, 5, ASYNC),
10222 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910223 };
10224
Ryan Sleevib8d7ea02018-05-07 20:01:0110225 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710226 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910227 // Negotiate SPDY to the proxy
10228 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610229 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710230 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910231
bnc87dcefc2017-05-25 12:47:5810232 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910233 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910234 TestCompletionCallback callback;
10235 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110236 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910237
10238 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110239 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910240 const HttpResponseInfo* response = trans->GetResponseInfo();
10241
bnc87dcefc2017-05-25 12:47:5810242 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910243 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010244 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110245 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910246
10247 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110248 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910249 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10250
wezca1070932016-05-26 20:30:5210251 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910252 EXPECT_TRUE(response->headers->IsKeepAlive());
10253
10254 EXPECT_EQ(200, response->headers->response_code());
10255 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10256
10257 std::string response_data;
10258 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110259 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910260 EXPECT_EQ("hello!", response_data);
10261
[email protected]029c83b62013-01-24 05:28:2010262 LoadTimingInfo load_timing_info;
10263 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10264 TestLoadTimingNotReusedWithPac(load_timing_info,
10265 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10266
[email protected]7c6f7ba2012-04-03 04:09:2910267 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210268 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910269 EXPECT_EQ(200, push_response->headers->response_code());
10270
10271 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110272 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910273 EXPECT_EQ("pushed", response_data);
10274
[email protected]029c83b62013-01-24 05:28:2010275 LoadTimingInfo push_load_timing_info;
10276 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10277 TestLoadTimingReusedWithPac(push_load_timing_info);
10278 // The transactions should share a socket ID, despite being for different
10279 // origins.
10280 EXPECT_EQ(load_timing_info.socket_log_id,
10281 push_load_timing_info.socket_log_id);
10282
[email protected]7c6f7ba2012-04-03 04:09:2910283 trans.reset();
10284 push_trans.reset();
10285 session->CloseAllConnections();
10286}
10287
[email protected]8c843192012-04-05 07:15:0010288// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110289TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510290 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910291 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510292 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10293 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010294 HttpRequestInfo request;
10295
10296 request.method = "GET";
bncce36dca22015-04-21 22:11:2310297 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010298 request.traffic_annotation =
10299 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010300
Ramin Halavatica8d5252018-03-12 05:33:4910301 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10302 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110303 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710304 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010305
10306 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210307 session_deps_.proxy_resolution_service->SetProxyDelegate(
10308 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010309
danakj1fd259a02016-04-16 03:17:0910310 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010311
Ryan Hamilton0239aac2018-05-19 00:03:1310312 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510313 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010314
Ryan Hamilton0239aac2018-05-19 00:03:1310315 spdy::SpdySerializedFrame push_rst(
10316 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010317
10318 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110319 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0010320 };
10321
Ryan Hamilton0239aac2018-05-19 00:03:1310322 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510323 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0010324
Ryan Hamilton0239aac2018-05-19 00:03:1310325 spdy::SpdySerializedFrame stream1_body(
10326 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0010327
Ryan Hamilton0239aac2018-05-19 00:03:1310328 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510329 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0010330
10331 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110332 CreateMockRead(stream1_reply, 1, ASYNC),
10333 CreateMockRead(stream2_syn, 2, ASYNC),
10334 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5910335 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0010336 };
10337
Ryan Sleevib8d7ea02018-05-07 20:01:0110338 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710339 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0010340 // Negotiate SPDY to the proxy
10341 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610342 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710343 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0010344
bnc87dcefc2017-05-25 12:47:5810345 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910346 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0010347 TestCompletionCallback callback;
10348 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110349 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0010350
10351 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110352 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010353 const HttpResponseInfo* response = trans->GetResponseInfo();
10354
wezca1070932016-05-26 20:30:5210355 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0010356 EXPECT_TRUE(response->headers->IsKeepAlive());
10357
10358 EXPECT_EQ(200, response->headers->response_code());
10359 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10360
10361 std::string response_data;
10362 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110363 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010364 EXPECT_EQ("hello!", response_data);
10365
10366 trans.reset();
10367 session->CloseAllConnections();
10368}
10369
tbansal8ef1d3e2016-02-03 04:05:4210370// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
10371// resources.
bncd16676a2016-07-20 16:23:0110372TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510373 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910374 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510375 proxy_delegate->set_trusted_spdy_proxy(
10376 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
10377
tbansal8ef1d3e2016-02-03 04:05:4210378 HttpRequestInfo request;
10379
10380 request.method = "GET";
10381 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010382 request.traffic_annotation =
10383 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210384
10385 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4910386 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10387 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210388 BoundTestNetLog log;
10389 session_deps_.net_log = log.bound().net_log();
10390
10391 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210392 session_deps_.proxy_resolution_service->SetProxyDelegate(
10393 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4210394
danakj1fd259a02016-04-16 03:17:0910395 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4210396
Ryan Hamilton0239aac2018-05-19 00:03:1310397 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510398 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310399 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510400 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4210401
10402 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110403 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510404 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4210405 };
10406
Ryan Hamilton0239aac2018-05-19 00:03:1310407 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1510408 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210409
Ryan Hamilton0239aac2018-05-19 00:03:1310410 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3310411 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4910412
Ryan Hamilton0239aac2018-05-19 00:03:1310413 spdy::SpdySerializedFrame stream1_body(
10414 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210415
Ryan Hamilton0239aac2018-05-19 00:03:1310416 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1510417 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210418
Ryan Hamilton0239aac2018-05-19 00:03:1310419 spdy::SpdySerializedFrame stream2_body(
10420 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210421
10422 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110423 CreateMockRead(stream1_reply, 1, ASYNC),
10424 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510425 CreateMockRead(stream1_body, 4, ASYNC),
10426 CreateMockRead(stream2_body, 5, ASYNC),
10427 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4210428 };
10429
Ryan Sleevib8d7ea02018-05-07 20:01:0110430 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4210431 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10432 // Negotiate SPDY to the proxy
10433 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610434 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4210435 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
10436
bnc87dcefc2017-05-25 12:47:5810437 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910438 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4210439 TestCompletionCallback callback;
10440 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110441 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4210442
10443 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110444 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210445 const HttpResponseInfo* response = trans->GetResponseInfo();
10446
wezca1070932016-05-26 20:30:5210447 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4210448 EXPECT_TRUE(response->headers->IsKeepAlive());
10449
10450 EXPECT_EQ(200, response->headers->response_code());
10451 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10452
10453 std::string response_data;
10454 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110455 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210456 EXPECT_EQ("hello!", response_data);
10457
10458 trans.reset();
10459 session->CloseAllConnections();
10460}
10461
[email protected]2df19bb2010-08-25 20:13:4610462// Test HTTPS connections to a site with a bad certificate, going through an
10463// HTTPS proxy
bncd16676a2016-07-20 16:23:0110464TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910465 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10466 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610467
10468 HttpRequestInfo request;
10469 request.method = "GET";
bncce36dca22015-04-21 22:11:2310470 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010471 request.traffic_annotation =
10472 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610473
10474 // Attempt to fetch the URL from a server with a bad cert
10475 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710476 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10477 "Host: www.example.org:443\r\n"
10478 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610479 };
10480
10481 MockRead bad_cert_reads[] = {
10482 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610483 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4610484 };
10485
10486 // Attempt to fetch the URL with a good cert
10487 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710488 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10489 "Host: www.example.org:443\r\n"
10490 "Proxy-Connection: keep-alive\r\n\r\n"),
10491 MockWrite("GET / HTTP/1.1\r\n"
10492 "Host: www.example.org\r\n"
10493 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610494 };
10495
10496 MockRead good_cert_reads[] = {
10497 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10498 MockRead("HTTP/1.0 200 OK\r\n"),
10499 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10500 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610501 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610502 };
10503
Ryan Sleevib8d7ea02018-05-07 20:01:0110504 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
10505 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0610506 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10507 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4610508
10509 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0710510 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10511 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10512 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4610513
10514 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0710515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10516 session_deps_.socket_factory->AddSocketDataProvider(&data);
10517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4610518
[email protected]49639fa2011-12-20 23:22:4110519 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610520
danakj1fd259a02016-04-16 03:17:0910521 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610522 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610523
tfarina42834112016-09-22 13:38:2010524 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110525 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610526
10527 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110528 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4610529
bnc691fda62016-08-12 00:43:1610530 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110531 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610532
10533 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110534 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4610535
bnc691fda62016-08-12 00:43:1610536 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610537
wezca1070932016-05-26 20:30:5210538 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610539 EXPECT_EQ(100, response->headers->GetContentLength());
10540}
10541
bncd16676a2016-07-20 16:23:0110542TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4210543 HttpRequestInfo request;
10544 request.method = "GET";
bncce36dca22015-04-21 22:11:2310545 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310546 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10547 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1010548 request.traffic_annotation =
10549 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210550
danakj1fd259a02016-04-16 03:17:0910551 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610552 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710553
[email protected]1c773ea12009-04-28 19:58:4210554 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310555 MockWrite(
10556 "GET / HTTP/1.1\r\n"
10557 "Host: www.example.org\r\n"
10558 "Connection: keep-alive\r\n"
10559 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210560 };
10561
10562 // Lastly, the server responds with the actual content.
10563 MockRead data_reads[] = {
10564 MockRead("HTTP/1.0 200 OK\r\n"),
10565 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10566 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610567 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210568 };
10569
Ryan Sleevib8d7ea02018-05-07 20:01:0110570 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710571 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210572
[email protected]49639fa2011-12-20 23:22:4110573 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210574
tfarina42834112016-09-22 13:38:2010575 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110576 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210577
10578 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110579 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210580}
10581
bncd16676a2016-07-20 16:23:0110582TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0010583 // Test user agent values, used both for the request header of the original
10584 // request, and the value returned by the HttpUserAgentSettings. nullptr means
10585 // no request header / no HttpUserAgentSettings object.
10586 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2910587
Matt Menked732ea42019-03-08 12:05:0010588 for (const char* setting_user_agent : kTestUserAgents) {
10589 if (!setting_user_agent) {
10590 session_deps_.http_user_agent_settings.reset();
10591 } else {
10592 session_deps_.http_user_agent_settings =
10593 std::make_unique<StaticHttpUserAgentSettings>(
10594 std::string() /* accept-language */, setting_user_agent);
10595 }
10596 session_deps_.proxy_resolution_service =
10597 ProxyResolutionService::CreateFixed("myproxy:70",
10598 TRAFFIC_ANNOTATION_FOR_TESTS);
10599 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10600 for (const char* request_user_agent : kTestUserAgents) {
10601 HttpRequestInfo request;
10602 request.method = "GET";
10603 request.url = GURL("https://www.example.org/");
10604 if (request_user_agent) {
10605 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10606 request_user_agent);
10607 }
10608 request.traffic_annotation =
10609 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710610
Matt Menked732ea42019-03-08 12:05:0010611 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2910612
Matt Menked732ea42019-03-08 12:05:0010613 std::string expected_request;
10614 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
10615 expected_request =
10616 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10617 "Host: www.example.org:443\r\n"
10618 "Proxy-Connection: keep-alive\r\n\r\n";
10619 } else {
10620 expected_request = base::StringPrintf(
10621 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10622 "Host: www.example.org:443\r\n"
10623 "Proxy-Connection: keep-alive\r\n"
10624 "User-Agent: %s\r\n\r\n",
10625 setting_user_agent);
10626 }
10627 MockWrite data_writes[] = {
10628 MockWrite(expected_request.c_str()),
10629 };
10630 MockRead data_reads[] = {
10631 // Return an error, so the transaction stops here (this test isn't
10632 // interested in the rest).
10633 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10634 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10635 MockRead("Proxy-Connection: close\r\n\r\n"),
10636 };
[email protected]da81f132010-08-18 23:39:2910637
Matt Menked732ea42019-03-08 12:05:0010638 StaticSocketDataProvider data(data_reads, data_writes);
10639 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2910640
Matt Menked732ea42019-03-08 12:05:0010641 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2910642
Matt Menked732ea42019-03-08 12:05:0010643 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10644 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10645
10646 rv = callback.WaitForResult();
10647 EXPECT_THAT(rv, IsOk());
10648 }
10649 }
[email protected]da81f132010-08-18 23:39:2910650}
10651
bncd16676a2016-07-20 16:23:0110652TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4210653 HttpRequestInfo request;
10654 request.method = "GET";
bncce36dca22015-04-21 22:11:2310655 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1610656 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
10657 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1010658 request.traffic_annotation =
10659 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210660
danakj1fd259a02016-04-16 03:17:0910661 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610662 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710663
[email protected]1c773ea12009-04-28 19:58:4210664 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310665 MockWrite(
10666 "GET / HTTP/1.1\r\n"
10667 "Host: www.example.org\r\n"
10668 "Connection: keep-alive\r\n"
10669 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210670 };
10671
10672 // Lastly, the server responds with the actual content.
10673 MockRead data_reads[] = {
10674 MockRead("HTTP/1.0 200 OK\r\n"),
10675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10676 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610677 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210678 };
10679
Ryan Sleevib8d7ea02018-05-07 20:01:0110680 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710681 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210682
[email protected]49639fa2011-12-20 23:22:4110683 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210684
tfarina42834112016-09-22 13:38:2010685 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110686 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210687
10688 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110689 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210690}
10691
bncd16676a2016-07-20 16:23:0110692TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210693 HttpRequestInfo request;
10694 request.method = "POST";
bncce36dca22015-04-21 22:11:2310695 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010696 request.traffic_annotation =
10697 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210698
danakj1fd259a02016-04-16 03:17:0910699 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610700 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710701
[email protected]1c773ea12009-04-28 19:58:4210702 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310703 MockWrite(
10704 "POST / HTTP/1.1\r\n"
10705 "Host: www.example.org\r\n"
10706 "Connection: keep-alive\r\n"
10707 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210708 };
10709
10710 // Lastly, the server responds with the actual content.
10711 MockRead data_reads[] = {
10712 MockRead("HTTP/1.0 200 OK\r\n"),
10713 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10714 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610715 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210716 };
10717
Ryan Sleevib8d7ea02018-05-07 20:01:0110718 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710719 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210720
[email protected]49639fa2011-12-20 23:22:4110721 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210722
tfarina42834112016-09-22 13:38:2010723 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110724 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210725
10726 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110727 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210728}
10729
bncd16676a2016-07-20 16:23:0110730TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210731 HttpRequestInfo request;
10732 request.method = "PUT";
bncce36dca22015-04-21 22:11:2310733 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010734 request.traffic_annotation =
10735 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210736
danakj1fd259a02016-04-16 03:17:0910737 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610738 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710739
[email protected]1c773ea12009-04-28 19:58:4210740 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310741 MockWrite(
10742 "PUT / HTTP/1.1\r\n"
10743 "Host: www.example.org\r\n"
10744 "Connection: keep-alive\r\n"
10745 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210746 };
10747
10748 // Lastly, the server responds with the actual content.
10749 MockRead data_reads[] = {
10750 MockRead("HTTP/1.0 200 OK\r\n"),
10751 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10752 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610753 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210754 };
10755
Ryan Sleevib8d7ea02018-05-07 20:01:0110756 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710757 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210758
[email protected]49639fa2011-12-20 23:22:4110759 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210760
tfarina42834112016-09-22 13:38:2010761 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110762 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210763
10764 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110765 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210766}
10767
bncd16676a2016-07-20 16:23:0110768TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210769 HttpRequestInfo request;
10770 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2310771 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010772 request.traffic_annotation =
10773 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210774
danakj1fd259a02016-04-16 03:17:0910775 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610776 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710777
[email protected]1c773ea12009-04-28 19:58:4210778 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1310779 MockWrite("HEAD / HTTP/1.1\r\n"
10780 "Host: www.example.org\r\n"
10781 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210782 };
10783
10784 // Lastly, the server responds with the actual content.
10785 MockRead data_reads[] = {
10786 MockRead("HTTP/1.0 200 OK\r\n"),
10787 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10788 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610789 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210790 };
10791
Ryan Sleevib8d7ea02018-05-07 20:01:0110792 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710793 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210794
[email protected]49639fa2011-12-20 23:22:4110795 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210796
tfarina42834112016-09-22 13:38:2010797 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110798 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210799
10800 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110801 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210802}
10803
bncd16676a2016-07-20 16:23:0110804TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4210805 HttpRequestInfo request;
10806 request.method = "GET";
bncce36dca22015-04-21 22:11:2310807 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210808 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010809 request.traffic_annotation =
10810 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210811
danakj1fd259a02016-04-16 03:17:0910812 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610813 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710814
[email protected]1c773ea12009-04-28 19:58:4210815 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310816 MockWrite(
10817 "GET / HTTP/1.1\r\n"
10818 "Host: www.example.org\r\n"
10819 "Connection: keep-alive\r\n"
10820 "Pragma: no-cache\r\n"
10821 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210822 };
10823
10824 // Lastly, the server responds with the actual content.
10825 MockRead data_reads[] = {
10826 MockRead("HTTP/1.0 200 OK\r\n"),
10827 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10828 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610829 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210830 };
10831
Ryan Sleevib8d7ea02018-05-07 20:01:0110832 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710833 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210834
[email protected]49639fa2011-12-20 23:22:4110835 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210836
tfarina42834112016-09-22 13:38:2010837 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110838 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210839
10840 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110841 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210842}
10843
bncd16676a2016-07-20 16:23:0110844TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4210845 HttpRequestInfo request;
10846 request.method = "GET";
bncce36dca22015-04-21 22:11:2310847 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210848 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010849 request.traffic_annotation =
10850 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210851
danakj1fd259a02016-04-16 03:17:0910852 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610853 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710854
[email protected]1c773ea12009-04-28 19:58:4210855 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310856 MockWrite(
10857 "GET / HTTP/1.1\r\n"
10858 "Host: www.example.org\r\n"
10859 "Connection: keep-alive\r\n"
10860 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210861 };
10862
10863 // Lastly, the server responds with the actual content.
10864 MockRead data_reads[] = {
10865 MockRead("HTTP/1.0 200 OK\r\n"),
10866 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10867 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610868 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210869 };
10870
Ryan Sleevib8d7ea02018-05-07 20:01:0110871 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710872 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210873
[email protected]49639fa2011-12-20 23:22:4110874 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210875
tfarina42834112016-09-22 13:38:2010876 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210878
10879 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110880 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210881}
10882
bncd16676a2016-07-20 16:23:0110883TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4210884 HttpRequestInfo request;
10885 request.method = "GET";
bncce36dca22015-04-21 22:11:2310886 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310887 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010888 request.traffic_annotation =
10889 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210890
danakj1fd259a02016-04-16 03:17:0910891 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610892 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710893
[email protected]1c773ea12009-04-28 19:58:4210894 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310895 MockWrite(
10896 "GET / HTTP/1.1\r\n"
10897 "Host: www.example.org\r\n"
10898 "Connection: keep-alive\r\n"
10899 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210900 };
10901
10902 // Lastly, the server responds with the actual content.
10903 MockRead data_reads[] = {
10904 MockRead("HTTP/1.0 200 OK\r\n"),
10905 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10906 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610907 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210908 };
10909
Ryan Sleevib8d7ea02018-05-07 20:01:0110910 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710911 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210912
[email protected]49639fa2011-12-20 23:22:4110913 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210914
tfarina42834112016-09-22 13:38:2010915 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110916 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210917
10918 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110919 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210920}
10921
bncd16676a2016-07-20 16:23:0110922TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4710923 HttpRequestInfo request;
10924 request.method = "GET";
bncce36dca22015-04-21 22:11:2310925 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310926 request.extra_headers.SetHeader("referer", "www.foo.com");
10927 request.extra_headers.SetHeader("hEllo", "Kitty");
10928 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010929 request.traffic_annotation =
10930 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4710931
danakj1fd259a02016-04-16 03:17:0910932 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610933 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710934
[email protected]270c6412010-03-29 22:02:4710935 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310936 MockWrite(
10937 "GET / HTTP/1.1\r\n"
10938 "Host: www.example.org\r\n"
10939 "Connection: keep-alive\r\n"
10940 "referer: www.foo.com\r\n"
10941 "hEllo: Kitty\r\n"
10942 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4710943 };
10944
10945 // Lastly, the server responds with the actual content.
10946 MockRead data_reads[] = {
10947 MockRead("HTTP/1.0 200 OK\r\n"),
10948 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10949 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610950 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4710951 };
10952
Ryan Sleevib8d7ea02018-05-07 20:01:0110953 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710954 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4710955
[email protected]49639fa2011-12-20 23:22:4110956 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4710957
tfarina42834112016-09-22 13:38:2010958 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110959 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4710960
10961 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110962 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4710963}
10964
bncd16676a2016-07-20 16:23:0110965TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710966 HttpRequestInfo request;
10967 request.method = "GET";
bncce36dca22015-04-21 22:11:2310968 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010969 request.traffic_annotation =
10970 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710971
Lily Houghton8c2f97d2018-01-22 05:06:5910972 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910973 ProxyResolutionService::CreateFixedFromPacResult(
10974 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110975 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710976 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210977
danakj1fd259a02016-04-16 03:17:0910978 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610979 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210980
[email protected]3cd17242009-06-23 02:59:0210981 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10982 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10983
10984 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410985 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10986 MockWrite("GET / HTTP/1.1\r\n"
10987 "Host: www.example.org\r\n"
10988 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210989
10990 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410991 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10992 MockRead("HTTP/1.0 200 OK\r\n"),
10993 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10994 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0210995
Ryan Sleevib8d7ea02018-05-07 20:01:0110996 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710997 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0210998
[email protected]49639fa2011-12-20 23:22:4110999 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211000
tfarina42834112016-09-22 13:38:2011001 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111002 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211003
11004 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111005 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211006
bnc691fda62016-08-12 00:43:1611007 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211008 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0211009
tbansal2ecbbc72016-10-06 17:15:4711010 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2011011 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611012 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011013 TestLoadTimingNotReusedWithPac(load_timing_info,
11014 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11015
[email protected]3cd17242009-06-23 02:59:0211016 std::string response_text;
bnc691fda62016-08-12 00:43:1611017 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111018 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211019 EXPECT_EQ("Payload", response_text);
11020}
11021
bncd16676a2016-07-20 16:23:0111022TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711023 HttpRequestInfo request;
11024 request.method = "GET";
bncce36dca22015-04-21 22:11:2311025 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011026 request.traffic_annotation =
11027 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711028
Lily Houghton8c2f97d2018-01-22 05:06:5911029 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911030 ProxyResolutionService::CreateFixedFromPacResult(
11031 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111032 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711033 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0211034
danakj1fd259a02016-04-16 03:17:0911035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611036 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0211037
[email protected]3cd17242009-06-23 02:59:0211038 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
11039 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11040
11041 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311042 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2411043 base::size(write_buffer)),
11044 MockWrite("GET / HTTP/1.1\r\n"
11045 "Host: www.example.org\r\n"
11046 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0211047
11048 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411049 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
11050 base::size(read_buffer)),
11051 MockRead("HTTP/1.0 200 OK\r\n"),
11052 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11053 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511054
Ryan Sleevib8d7ea02018-05-07 20:01:0111055 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711056 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511057
[email protected]8ddf8322012-02-23 18:08:0611058 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711059 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3511060
[email protected]49639fa2011-12-20 23:22:4111061 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511062
tfarina42834112016-09-22 13:38:2011063 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111064 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511065
11066 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111067 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511068
[email protected]029c83b62013-01-24 05:28:2011069 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611070 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011071 TestLoadTimingNotReusedWithPac(load_timing_info,
11072 CONNECT_TIMING_HAS_SSL_TIMES);
11073
bnc691fda62016-08-12 00:43:1611074 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211075 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711076 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511077
11078 std::string response_text;
bnc691fda62016-08-12 00:43:1611079 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111080 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511081 EXPECT_EQ("Payload", response_text);
11082}
11083
bncd16676a2016-07-20 16:23:0111084TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2011085 HttpRequestInfo request;
11086 request.method = "GET";
bncce36dca22015-04-21 22:11:2311087 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011088 request.traffic_annotation =
11089 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2011090
Ramin Halavatica8d5252018-03-12 05:33:4911091 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11092 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111093 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711094 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2011095
danakj1fd259a02016-04-16 03:17:0911096 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611097 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2011098
11099 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
11100 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
11101
11102 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411103 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
11104 MockWrite("GET / HTTP/1.1\r\n"
11105 "Host: www.example.org\r\n"
11106 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2011107
11108 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411109 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
11110 MockRead("HTTP/1.0 200 OK\r\n"),
11111 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11112 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2011113
Ryan Sleevib8d7ea02018-05-07 20:01:0111114 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711115 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2011116
11117 TestCompletionCallback callback;
11118
tfarina42834112016-09-22 13:38:2011119 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111120 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2011121
11122 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111123 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011124
bnc691fda62016-08-12 00:43:1611125 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211126 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2011127
11128 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611129 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011130 TestLoadTimingNotReused(load_timing_info,
11131 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11132
11133 std::string response_text;
bnc691fda62016-08-12 00:43:1611134 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111135 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2011136 EXPECT_EQ("Payload", response_text);
11137}
11138
bncd16676a2016-07-20 16:23:0111139TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711140 HttpRequestInfo request;
11141 request.method = "GET";
bncce36dca22015-04-21 22:11:2311142 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011143 request.traffic_annotation =
11144 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711145
Lily Houghton8c2f97d2018-01-22 05:06:5911146 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911147 ProxyResolutionService::CreateFixedFromPacResult(
11148 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111149 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711150 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511151
danakj1fd259a02016-04-16 03:17:0911152 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611153 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511154
[email protected]e0c27be2009-07-15 13:09:3511155 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11156 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711157 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311158 0x05, // Version
11159 0x01, // Command (CONNECT)
11160 0x00, // Reserved.
11161 0x03, // Address type (DOMAINNAME).
11162 0x0F, // Length of domain (15)
11163 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11164 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711165 };
[email protected]e0c27be2009-07-15 13:09:3511166 const char kSOCKS5OkResponse[] =
11167 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11168
11169 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411170 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11171 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11172 MockWrite("GET / HTTP/1.1\r\n"
11173 "Host: www.example.org\r\n"
11174 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511175
11176 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411177 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11178 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11179 MockRead("HTTP/1.0 200 OK\r\n"),
11180 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11181 MockRead("Payload"),
11182 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511183
Ryan Sleevib8d7ea02018-05-07 20:01:0111184 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711185 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511186
[email protected]49639fa2011-12-20 23:22:4111187 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511188
tfarina42834112016-09-22 13:38:2011189 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111190 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511191
11192 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111193 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511194
bnc691fda62016-08-12 00:43:1611195 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211196 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711197 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511198
[email protected]029c83b62013-01-24 05:28:2011199 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611200 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011201 TestLoadTimingNotReusedWithPac(load_timing_info,
11202 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11203
[email protected]e0c27be2009-07-15 13:09:3511204 std::string response_text;
bnc691fda62016-08-12 00:43:1611205 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111206 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511207 EXPECT_EQ("Payload", response_text);
11208}
11209
bncd16676a2016-07-20 16:23:0111210TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711211 HttpRequestInfo request;
11212 request.method = "GET";
bncce36dca22015-04-21 22:11:2311213 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011214 request.traffic_annotation =
11215 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711216
Lily Houghton8c2f97d2018-01-22 05:06:5911217 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911218 ProxyResolutionService::CreateFixedFromPacResult(
11219 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111220 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711221 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511222
danakj1fd259a02016-04-16 03:17:0911223 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611224 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511225
[email protected]e0c27be2009-07-15 13:09:3511226 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11227 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711228 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311229 0x05, // Version
11230 0x01, // Command (CONNECT)
11231 0x00, // Reserved.
11232 0x03, // Address type (DOMAINNAME).
11233 0x0F, // Length of domain (15)
11234 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11235 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711236 };
11237
[email protected]e0c27be2009-07-15 13:09:3511238 const char kSOCKS5OkResponse[] =
11239 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11240
11241 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411242 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311243 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411244 base::size(kSOCKS5OkRequest)),
11245 MockWrite("GET / HTTP/1.1\r\n"
11246 "Host: www.example.org\r\n"
11247 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511248
11249 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411250 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11251 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11252 MockRead("HTTP/1.0 200 OK\r\n"),
11253 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11254 MockRead("Payload"),
11255 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211256
Ryan Sleevib8d7ea02018-05-07 20:01:0111257 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711258 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211259
[email protected]8ddf8322012-02-23 18:08:0611260 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211262
[email protected]49639fa2011-12-20 23:22:4111263 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211264
tfarina42834112016-09-22 13:38:2011265 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111266 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211267
11268 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111269 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211270
bnc691fda62016-08-12 00:43:1611271 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211272 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711273 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211274
[email protected]029c83b62013-01-24 05:28:2011275 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611276 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011277 TestLoadTimingNotReusedWithPac(load_timing_info,
11278 CONNECT_TIMING_HAS_SSL_TIMES);
11279
[email protected]3cd17242009-06-23 02:59:0211280 std::string response_text;
bnc691fda62016-08-12 00:43:1611281 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111282 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211283 EXPECT_EQ("Payload", response_text);
11284}
11285
[email protected]448d4ca52012-03-04 04:12:2311286namespace {
11287
Matt Menkef6edce752019-03-19 17:21:5611288// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611289
Matt Menkef6edce752019-03-19 17:21:5611290struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611291 std::string proxy_server;
11292 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611293 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811294 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611295};
11296
Matt Menkef6edce752019-03-19 17:21:5611297std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711298 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911299 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611300
bnc525e175a2016-06-20 12:36:4011301 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311302 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111303 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211304 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111305 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211306 url::SchemeHostPort("https", "host.with.alternate", 443),
Matt Menke9aa86262019-08-21 15:52:0711307 NetworkIsolationKey(), alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611308
11309 return session;
11310}
11311
Matt Menkef6edce752019-03-19 17:21:5611312int GroupIdTransactionHelper(const std::string& url,
11313 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611314 HttpRequestInfo request;
11315 request.method = "GET";
11316 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1011317 request.traffic_annotation =
11318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611319
bnc691fda62016-08-12 00:43:1611320 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2711321
[email protected]49639fa2011-12-20 23:22:4111322 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0611323
11324 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2011325 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0611326}
11327
[email protected]448d4ca52012-03-04 04:12:2311328} // namespace
11329
Matt Menkef6edce752019-03-19 17:21:5611330TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
11331 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311332 {
Matt Menkef6edce752019-03-19 17:21:5611333 "", // unused
11334 "http://www.example.org/direct",
11335 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11336 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911337 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611338 false,
bncce36dca22015-04-21 22:11:2311339 },
11340 {
Matt Menkef6edce752019-03-19 17:21:5611341 "", // unused
11342 "http://[2001:1418:13:1::25]/direct",
11343 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
11344 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911345 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611346 false,
bncce36dca22015-04-21 22:11:2311347 },
[email protected]04e5be32009-06-26 20:00:3111348
bncce36dca22015-04-21 22:11:2311349 // SSL Tests
11350 {
Matt Menkef6edce752019-03-19 17:21:5611351 "", // unused
11352 "https://www.example.org/direct_ssl",
11353 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11354 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911355 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611356 true,
bncce36dca22015-04-21 22:11:2311357 },
11358 {
Matt Menkef6edce752019-03-19 17:21:5611359 "", // unused
11360 "https://[2001:1418:13:1::25]/direct",
11361 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
11362 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911363 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611364 true,
bncce36dca22015-04-21 22:11:2311365 },
11366 {
Matt Menkef6edce752019-03-19 17:21:5611367 "", // unused
11368 "https://host.with.alternate/direct",
11369 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11370 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911371 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611372 true,
bncce36dca22015-04-21 22:11:2311373 },
[email protected]2d731a32010-04-29 01:04:0611374 };
[email protected]2ff8b312010-04-26 22:20:5411375
Avi Drissman4365a4782018-12-28 19:26:2411376 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911377 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911378 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11379 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911380 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611381 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611382
mmenkee65e7af2015-10-13 17:16:4211383 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5611384 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611385 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911386 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011387 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
11388 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4811389 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611390
11391 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611392 GroupIdTransactionHelper(tests[i].url, session.get()));
11393 EXPECT_EQ(tests[i].expected_group_id,
11394 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2311395 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0611396 }
[email protected]2d731a32010-04-29 01:04:0611397}
11398
Matt Menkef6edce752019-03-19 17:21:5611399TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
11400 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311401 {
Matt Menke4802de62019-03-08 22:47:5011402 "http_proxy",
11403 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611404 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11405 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911406 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011407 false,
bncce36dca22015-04-21 22:11:2311408 },
[email protected]2d731a32010-04-29 01:04:0611409
bncce36dca22015-04-21 22:11:2311410 // SSL Tests
11411 {
Matt Menke4802de62019-03-08 22:47:5011412 "http_proxy",
11413 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5611414 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11415 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911416 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011417 true,
bncce36dca22015-04-21 22:11:2311418 },
[email protected]af3490e2010-10-16 21:02:2911419
bncce36dca22015-04-21 22:11:2311420 {
Matt Menke4802de62019-03-08 22:47:5011421 "http_proxy",
11422 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611423 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11424 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911425 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011426 true,
bncce36dca22015-04-21 22:11:2311427 },
[email protected]2d731a32010-04-29 01:04:0611428 };
11429
Avi Drissman4365a4782018-12-28 19:26:2411430 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911431 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911432 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11433 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911434 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611435 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611436
mmenkee65e7af2015-10-13 17:16:4211437 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0611438
Matt Menkee8648fa2019-01-17 16:47:0711439 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
11440 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5611441 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3611442 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911443 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011444 mock_pool_manager->SetSocketPool(proxy_server,
11445 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4811446 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611447
11448 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611449 GroupIdTransactionHelper(tests[i].url, session.get()));
11450 EXPECT_EQ(tests[i].expected_group_id,
11451 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0611452 }
[email protected]2d731a32010-04-29 01:04:0611453}
11454
Matt Menkef6edce752019-03-19 17:21:5611455TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
11456 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311457 {
Matt Menke4802de62019-03-08 22:47:5011458 "socks4://socks_proxy:1080",
11459 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5611460 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11461 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911462 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011463 false,
bncce36dca22015-04-21 22:11:2311464 },
11465 {
Matt Menke4802de62019-03-08 22:47:5011466 "socks5://socks_proxy:1080",
11467 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5611468 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11469 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911470 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011471 false,
bncce36dca22015-04-21 22:11:2311472 },
[email protected]2d731a32010-04-29 01:04:0611473
bncce36dca22015-04-21 22:11:2311474 // SSL Tests
11475 {
Matt Menke4802de62019-03-08 22:47:5011476 "socks4://socks_proxy:1080",
11477 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5611478 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11479 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911480 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011481 true,
bncce36dca22015-04-21 22:11:2311482 },
11483 {
Matt Menke4802de62019-03-08 22:47:5011484 "socks5://socks_proxy:1080",
11485 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5611486 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11487 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911488 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011489 true,
bncce36dca22015-04-21 22:11:2311490 },
[email protected]af3490e2010-10-16 21:02:2911491
bncce36dca22015-04-21 22:11:2311492 {
Matt Menke4802de62019-03-08 22:47:5011493 "socks4://socks_proxy:1080",
11494 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611495 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11496 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911497 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011498 true,
bncce36dca22015-04-21 22:11:2311499 },
[email protected]04e5be32009-06-26 20:00:3111500 };
11501
Avi Drissman4365a4782018-12-28 19:26:2411502 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911503 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911504 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11505 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911506 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611507 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0211508
mmenkee65e7af2015-10-13 17:16:4211509 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3111510
Matt Menkee8648fa2019-01-17 16:47:0711511 ProxyServer proxy_server(
11512 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
11513 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5611514 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611515 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911516 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011517 mock_pool_manager->SetSocketPool(proxy_server,
11518 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4811519 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3111520
bnc691fda62016-08-12 00:43:1611521 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3111522
[email protected]2d731a32010-04-29 01:04:0611523 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611524 GroupIdTransactionHelper(tests[i].url, session.get()));
11525 EXPECT_EQ(tests[i].expected_group_id,
11526 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3111527 }
11528}
11529
bncd16676a2016-07-20 16:23:0111530TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2711531 HttpRequestInfo request;
11532 request.method = "GET";
bncce36dca22015-04-21 22:11:2311533 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011534 request.traffic_annotation =
11535 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711536
Ramin Halavatica8d5252018-03-12 05:33:4911537 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11538 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3211539
[email protected]69719062010-01-05 20:09:2111540 // This simulates failure resolving all hostnames; that means we will fail
11541 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0711542 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3211543
danakj1fd259a02016-04-16 03:17:0911544 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611545 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2511546
[email protected]49639fa2011-12-20 23:22:4111547 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2511548
tfarina42834112016-09-22 13:38:2011549 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111550 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2511551
[email protected]9172a982009-06-06 00:30:2511552 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111553 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2511554}
11555
[email protected]0877e3d2009-10-17 22:29:5711556// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0111557TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5711558 HttpRequestInfo request;
11559 request.method = "GET";
11560 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011561 request.traffic_annotation =
11562 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711563
11564 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0611565 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711566 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111567 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0711568 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911569 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711570
[email protected]49639fa2011-12-20 23:22:4111571 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711572
bnc691fda62016-08-12 00:43:1611573 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711574
tfarina42834112016-09-22 13:38:2011575 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111576 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711577
11578 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111579 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5911580
11581 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611582 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911583 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711584}
11585
zmo9528c9f42015-08-04 22:12:0811586// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0111587TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5711588 HttpRequestInfo request;
11589 request.method = "GET";
11590 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011591 request.traffic_annotation =
11592 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711593
11594 MockRead data_reads[] = {
11595 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0611596 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711597 };
11598
Ryan Sleevib8d7ea02018-05-07 20:01:0111599 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711600 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911601 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711602
[email protected]49639fa2011-12-20 23:22:4111603 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711604
bnc691fda62016-08-12 00:43:1611605 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711606
tfarina42834112016-09-22 13:38:2011607 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111608 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711609
11610 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111611 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811612
bnc691fda62016-08-12 00:43:1611613 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211614 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0811615
wezca1070932016-05-26 20:30:5211616 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0811617 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11618
11619 std::string response_data;
bnc691fda62016-08-12 00:43:1611620 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111621 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811622 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5911623
11624 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611625 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911626 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711627}
11628
11629// Make sure that a dropped connection while draining the body for auth
11630// restart does the right thing.
bncd16676a2016-07-20 16:23:0111631TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5711632 HttpRequestInfo request;
11633 request.method = "GET";
bncce36dca22015-04-21 22:11:2311634 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011635 request.traffic_annotation =
11636 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711637
11638 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311639 MockWrite(
11640 "GET / HTTP/1.1\r\n"
11641 "Host: www.example.org\r\n"
11642 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711643 };
11644
11645 MockRead data_reads1[] = {
11646 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
11647 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11648 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11649 MockRead("Content-Length: 14\r\n\r\n"),
11650 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0611651 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711652 };
11653
Ryan Sleevib8d7ea02018-05-07 20:01:0111654 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0711655 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5711656
bnc691fda62016-08-12 00:43:1611657 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5711658 // be issuing -- the final header line contains the credentials.
11659 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311660 MockWrite(
11661 "GET / HTTP/1.1\r\n"
11662 "Host: www.example.org\r\n"
11663 "Connection: keep-alive\r\n"
11664 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711665 };
11666
11667 // Lastly, the server responds with the actual content.
11668 MockRead data_reads2[] = {
11669 MockRead("HTTP/1.1 200 OK\r\n"),
11670 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11671 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611672 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711673 };
11674
Ryan Sleevib8d7ea02018-05-07 20:01:0111675 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0711676 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0911677 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711678
[email protected]49639fa2011-12-20 23:22:4111679 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5711680
bnc691fda62016-08-12 00:43:1611681 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011682
tfarina42834112016-09-22 13:38:2011683 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111684 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711685
11686 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111687 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711688
bnc691fda62016-08-12 00:43:1611689 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211690 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811691 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5711692
[email protected]49639fa2011-12-20 23:22:4111693 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5711694
bnc691fda62016-08-12 00:43:1611695 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0111696 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711697
11698 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111699 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711700
bnc691fda62016-08-12 00:43:1611701 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211702 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811703 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5711704 EXPECT_EQ(100, response->headers->GetContentLength());
11705}
11706
11707// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0111708TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4911709 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11710 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711711
11712 HttpRequestInfo request;
11713 request.method = "GET";
bncce36dca22015-04-21 22:11:2311714 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011715 request.traffic_annotation =
11716 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711717
11718 MockRead proxy_reads[] = {
11719 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0611720 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5711721 };
11722
Ryan Sleevib8d7ea02018-05-07 20:01:0111723 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0611724 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5711725
[email protected]bb88e1d32013-05-03 23:11:0711726 session_deps_.socket_factory->AddSocketDataProvider(&data);
11727 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5711728
[email protected]49639fa2011-12-20 23:22:4111729 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711730
[email protected]bb88e1d32013-05-03 23:11:0711731 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5711732
danakj1fd259a02016-04-16 03:17:0911733 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611734 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711735
tfarina42834112016-09-22 13:38:2011736 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111737 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711738
11739 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111740 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5711741}
11742
bncd16676a2016-07-20 16:23:0111743TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4611744 HttpRequestInfo request;
11745 request.method = "GET";
bncce36dca22015-04-21 22:11:2311746 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011747 request.traffic_annotation =
11748 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4611749
danakj1fd259a02016-04-16 03:17:0911750 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611751 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711752
[email protected]e22e1362009-11-23 21:31:1211753 MockRead data_reads[] = {
11754 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611755 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1211756 };
[email protected]9492e4a2010-02-24 00:58:4611757
Ryan Sleevib8d7ea02018-05-07 20:01:0111758 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711759 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4611760
[email protected]49639fa2011-12-20 23:22:4111761 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4611762
tfarina42834112016-09-22 13:38:2011763 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111764 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4611765
robpercival214763f2016-07-01 23:27:0111766 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4611767
bnc691fda62016-08-12 00:43:1611768 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211769 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4611770
wezca1070932016-05-26 20:30:5211771 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4611772 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11773
11774 std::string response_data;
bnc691fda62016-08-12 00:43:1611775 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111776 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1211777}
11778
bncd16676a2016-07-20 16:23:0111779TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1511780 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5211781 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1411782 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2111783 UploadFileElementReader::ScopedOverridingContentLengthForTests
11784 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3311785
danakj1fd259a02016-04-16 03:17:0911786 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911787 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411788 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0711789 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211790 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711791
11792 HttpRequestInfo request;
11793 request.method = "POST";
bncce36dca22015-04-21 22:11:2311794 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711795 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011796 request.traffic_annotation =
11797 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711798
danakj1fd259a02016-04-16 03:17:0911799 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611800 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3311801
11802 MockRead data_reads[] = {
11803 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11804 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0611805 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3311806 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111807 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711808 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3311809
[email protected]49639fa2011-12-20 23:22:4111810 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3311811
tfarina42834112016-09-22 13:38:2011812 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111813 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3311814
11815 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111816 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3311817
bnc691fda62016-08-12 00:43:1611818 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211819 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3311820
maksim.sisove869bf52016-06-23 17:11:5211821 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3311822
[email protected]dd3aa792013-07-16 19:10:2311823 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3311824}
11825
bncd16676a2016-07-20 16:23:0111826TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1511827 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5211828 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3611829 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4811830 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
11831 base::WriteFile(temp_file, temp_file_content.c_str(),
11832 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1111833 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3611834
danakj1fd259a02016-04-16 03:17:0911835 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911836 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411837 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0711838 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211839 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711840
11841 HttpRequestInfo request;
11842 request.method = "POST";
bncce36dca22015-04-21 22:11:2311843 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711844 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011845 request.traffic_annotation =
11846 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711847
[email protected]999dd8c2013-11-12 06:45:5411848 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0911849 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611850 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3611851
Ryan Sleevib8d7ea02018-05-07 20:01:0111852 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0711853 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3611854
[email protected]49639fa2011-12-20 23:22:4111855 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3611856
tfarina42834112016-09-22 13:38:2011857 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3611859
11860 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111861 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3611862
[email protected]dd3aa792013-07-16 19:10:2311863 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3611864}
11865
bncd16676a2016-07-20 16:23:0111866TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0311867 class FakeUploadElementReader : public UploadElementReader {
11868 public:
Chris Watkins7a41d3552017-12-01 02:13:2711869 FakeUploadElementReader() = default;
11870 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0311871
Matt Menkecc1d3a902018-02-05 18:27:3311872 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0311873
11874 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3311875 int Init(CompletionOnceCallback callback) override {
11876 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0311877 return ERR_IO_PENDING;
11878 }
avibf0746c2015-12-09 19:53:1411879 uint64_t GetContentLength() const override { return 0; }
11880 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2011881 int Read(IOBuffer* buf,
11882 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3311883 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0311884 return ERR_FAILED;
11885 }
11886
11887 private:
Matt Menkecc1d3a902018-02-05 18:27:3311888 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0311889 };
11890
11891 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0911892 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11893 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2211894 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0311895
11896 HttpRequestInfo request;
11897 request.method = "POST";
bncce36dca22015-04-21 22:11:2311898 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0311899 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011900 request.traffic_annotation =
11901 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0311902
danakj1fd259a02016-04-16 03:17:0911903 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5811904 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911905 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0311906
11907 StaticSocketDataProvider data;
11908 session_deps_.socket_factory->AddSocketDataProvider(&data);
11909
11910 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2011911 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5511913 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0311914
11915 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3311916 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
11917 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0311918
11919 // Return Init()'s result after the transaction gets destroyed.
11920 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3311921 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0311922}
11923
[email protected]aeefc9e82010-02-19 16:18:2711924// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0111925TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2711926 HttpRequestInfo request;
11927 request.method = "GET";
bncce36dca22015-04-21 22:11:2311928 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011929 request.traffic_annotation =
11930 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2711931
11932 // First transaction will request a resource and receive a Basic challenge
11933 // with realm="first_realm".
11934 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311935 MockWrite(
11936 "GET / HTTP/1.1\r\n"
11937 "Host: www.example.org\r\n"
11938 "Connection: keep-alive\r\n"
11939 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711940 };
11941 MockRead data_reads1[] = {
11942 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11943 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11944 "\r\n"),
11945 };
11946
bnc691fda62016-08-12 00:43:1611947 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2711948 // for first_realm. The server will reject and provide a challenge with
11949 // second_realm.
11950 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311951 MockWrite(
11952 "GET / HTTP/1.1\r\n"
11953 "Host: www.example.org\r\n"
11954 "Connection: keep-alive\r\n"
11955 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
11956 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711957 };
11958 MockRead data_reads2[] = {
11959 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11960 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
11961 "\r\n"),
11962 };
11963
11964 // This again fails, and goes back to first_realm. Make sure that the
11965 // entry is removed from cache.
11966 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2311967 MockWrite(
11968 "GET / HTTP/1.1\r\n"
11969 "Host: www.example.org\r\n"
11970 "Connection: keep-alive\r\n"
11971 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
11972 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711973 };
11974 MockRead data_reads3[] = {
11975 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11976 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11977 "\r\n"),
11978 };
11979
11980 // Try one last time (with the correct password) and get the resource.
11981 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2311982 MockWrite(
11983 "GET / HTTP/1.1\r\n"
11984 "Host: www.example.org\r\n"
11985 "Connection: keep-alive\r\n"
11986 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
11987 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711988 };
11989 MockRead data_reads4[] = {
11990 MockRead("HTTP/1.1 200 OK\r\n"
11991 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5011992 "Content-Length: 5\r\n"
11993 "\r\n"
11994 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2711995 };
11996
Ryan Sleevib8d7ea02018-05-07 20:01:0111997 StaticSocketDataProvider data1(data_reads1, data_writes1);
11998 StaticSocketDataProvider data2(data_reads2, data_writes2);
11999 StaticSocketDataProvider data3(data_reads3, data_writes3);
12000 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0712001 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12002 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12003 session_deps_.socket_factory->AddSocketDataProvider(&data3);
12004 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2712005
[email protected]49639fa2011-12-20 23:22:4112006 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2712007
danakj1fd259a02016-04-16 03:17:0912008 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612009 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5012010
[email protected]aeefc9e82010-02-19 16:18:2712011 // Issue the first request with Authorize headers. There should be a
12012 // password prompt for first_realm waiting to be filled in after the
12013 // transaction completes.
tfarina42834112016-09-22 13:38:2012014 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112015 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712016 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112017 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612018 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212019 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812020 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212021 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412022 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312023 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412024 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912025 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712026
12027 // Issue the second request with an incorrect password. There should be a
12028 // password prompt for second_realm waiting to be filled in after the
12029 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4112030 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1612031 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
12032 callback2.callback());
robpercival214763f2016-07-01 23:27:0112033 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712034 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0112035 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612036 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212037 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812038 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212039 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412040 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312041 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412042 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912043 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712044
12045 // Issue the third request with another incorrect password. There should be
12046 // a password prompt for first_realm waiting to be filled in. If the password
12047 // prompt is not present, it indicates that the HttpAuthCacheEntry for
12048 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4112049 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1612050 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
12051 callback3.callback());
robpercival214763f2016-07-01 23:27:0112052 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712053 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0112054 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612055 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212056 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812057 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5212058 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0412059 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4312060 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0412061 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1912062 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2712063
12064 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4112065 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1612066 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
12067 callback4.callback());
robpercival214763f2016-07-01 23:27:0112068 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2712069 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0112070 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1612071 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212072 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5812073 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2712074}
12075
Bence Béky230ac612017-08-30 19:17:0812076// Regression test for https://crbug.com/754395.
12077TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
12078 MockRead data_reads[] = {
12079 MockRead("HTTP/1.1 200 OK\r\n"),
12080 MockRead(kAlternativeServiceHttpHeader),
12081 MockRead("\r\n"),
12082 MockRead("hello world"),
12083 MockRead(SYNCHRONOUS, OK),
12084 };
12085
12086 HttpRequestInfo request;
12087 request.method = "GET";
12088 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012089 request.traffic_annotation =
12090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0812091
Ryan Sleevib8d7ea02018-05-07 20:01:0112092 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0812093 session_deps_.socket_factory->AddSocketDataProvider(&data);
12094
12095 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912096 ssl.ssl_info.cert =
12097 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12098 ASSERT_TRUE(ssl.ssl_info.cert);
12099 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0812100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12101
12102 TestCompletionCallback callback;
12103
12104 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12105 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12106
12107 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12108 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12109
12110 url::SchemeHostPort test_server(request.url);
12111 HttpServerProperties* http_server_properties =
12112 session->http_server_properties();
12113 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912114 http_server_properties
12115 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12116 .empty());
Bence Béky230ac612017-08-30 19:17:0812117
12118 EXPECT_THAT(callback.WaitForResult(), IsOk());
12119
12120 const HttpResponseInfo* response = trans.GetResponseInfo();
12121 ASSERT_TRUE(response);
12122 ASSERT_TRUE(response->headers);
12123 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12124 EXPECT_FALSE(response->was_fetched_via_spdy);
12125 EXPECT_FALSE(response->was_alpn_negotiated);
12126
12127 std::string response_data;
12128 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12129 EXPECT_EQ("hello world", response_data);
12130
12131 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912132 http_server_properties
12133 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12134 .empty());
Bence Béky230ac612017-08-30 19:17:0812135}
12136
bncd16676a2016-07-20 16:23:0112137TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5212138 MockRead data_reads[] = {
12139 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312140 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212141 MockRead("\r\n"),
12142 MockRead("hello world"),
12143 MockRead(SYNCHRONOUS, OK),
12144 };
12145
12146 HttpRequestInfo request;
12147 request.method = "GET";
bncb26024382016-06-29 02:39:4512148 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012149 request.traffic_annotation =
12150 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212151
Ryan Sleevib8d7ea02018-05-07 20:01:0112152 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212153 session_deps_.socket_factory->AddSocketDataProvider(&data);
12154
bncb26024382016-06-29 02:39:4512155 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912156 ssl.ssl_info.cert =
12157 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12158 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512159 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12160
bncc958faa2015-07-31 18:14:5212161 TestCompletionCallback callback;
12162
danakj1fd259a02016-04-16 03:17:0912163 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612164 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212165
tfarina42834112016-09-22 13:38:2012166 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112167 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212168
bncb26024382016-06-29 02:39:4512169 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012170 HttpServerProperties* http_server_properties =
12171 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412172 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912173 http_server_properties
12174 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12175 .empty());
bncc958faa2015-07-31 18:14:5212176
robpercival214763f2016-07-01 23:27:0112177 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212178
bnc691fda62016-08-12 00:43:1612179 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212180 ASSERT_TRUE(response);
12181 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212182 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12183 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212184 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212185
12186 std::string response_data;
bnc691fda62016-08-12 00:43:1612187 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212188 EXPECT_EQ("hello world", response_data);
12189
zhongyic4de03032017-05-19 04:07:3412190 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912191 http_server_properties->GetAlternativeServiceInfos(test_server,
12192 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412193 ASSERT_EQ(1u, alternative_service_info_vector.size());
12194 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12195 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412196 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212197}
12198
Matt Menke3233d8f22019-08-20 21:01:4912199TEST_F(HttpNetworkTransactionTest,
12200 HonorAlternativeServiceHeaderWithNetworkIsolationKey) {
12201 base::test::ScopedFeatureList feature_list;
12202 feature_list.InitWithFeatures(
12203 // enabled_features
12204 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
12205 // Need to partition connections by NetworkIsolationKey for
12206 // SpdySessionKeys to include NetworkIsolationKeys.
12207 features::kPartitionConnectionsByNetworkIsolationKey},
12208 // disabled_features
12209 {});
12210 // Since HttpServerProperties caches the feature value, have to create a new
12211 // one.
12212 session_deps_.http_server_properties =
12213 std::make_unique<HttpServerProperties>();
12214
12215 const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
12216 const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
12217 const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
12218 const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
12219
12220 MockRead data_reads[] = {
12221 MockRead("HTTP/1.1 200 OK\r\n"),
12222 MockRead(kAlternativeServiceHttpHeader),
12223 MockRead("\r\n"),
12224 MockRead("hello world"),
12225 MockRead(SYNCHRONOUS, OK),
12226 };
12227
12228 HttpRequestInfo request;
12229 request.method = "GET";
12230 request.url = GURL("https://www.example.org/");
12231 request.traffic_annotation =
12232 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12233 request.network_isolation_key = kNetworkIsolationKey1;
12234
12235 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12236 session_deps_.socket_factory->AddSocketDataProvider(&data);
12237
12238 SSLSocketDataProvider ssl(ASYNC, OK);
12239 ssl.ssl_info.cert =
12240 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12241 ASSERT_TRUE(ssl.ssl_info.cert);
12242 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12243
12244 TestCompletionCallback callback;
12245
12246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12247 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12248
12249 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12250 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12251
12252 url::SchemeHostPort test_server(request.url);
12253 HttpServerProperties* http_server_properties =
12254 session->http_server_properties();
12255 EXPECT_TRUE(
12256 http_server_properties
12257 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey1)
12258 .empty());
12259
12260 EXPECT_THAT(callback.WaitForResult(), IsOk());
12261
12262 const HttpResponseInfo* response = trans.GetResponseInfo();
12263 ASSERT_TRUE(response);
12264 ASSERT_TRUE(response->headers);
12265 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12266 EXPECT_FALSE(response->was_fetched_via_spdy);
12267 EXPECT_FALSE(response->was_alpn_negotiated);
12268
12269 std::string response_data;
12270 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
12271 EXPECT_EQ("hello world", response_data);
12272
12273 AlternativeServiceInfoVector alternative_service_info_vector =
12274 http_server_properties->GetAlternativeServiceInfos(test_server,
12275 kNetworkIsolationKey1);
12276 ASSERT_EQ(1u, alternative_service_info_vector.size());
12277 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12278 EXPECT_EQ(alternative_service,
12279 alternative_service_info_vector[0].alternative_service());
12280
12281 // Make sure the alternative service information is only associated with
12282 // kNetworkIsolationKey1.
12283 EXPECT_TRUE(
12284 http_server_properties
12285 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12286 .empty());
12287 EXPECT_TRUE(
12288 http_server_properties
12289 ->GetAlternativeServiceInfos(test_server, kNetworkIsolationKey2)
12290 .empty());
12291}
12292
bnce3dd56f2016-06-01 10:37:1112293// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0112294TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112295 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1112296 MockRead data_reads[] = {
12297 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312298 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1112299 MockRead("\r\n"),
12300 MockRead("hello world"),
12301 MockRead(SYNCHRONOUS, OK),
12302 };
12303
12304 HttpRequestInfo request;
12305 request.method = "GET";
12306 request.url = GURL("http://www.example.org/");
12307 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012308 request.traffic_annotation =
12309 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112310
Ryan Sleevib8d7ea02018-05-07 20:01:0112311 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112312 session_deps_.socket_factory->AddSocketDataProvider(&data);
12313
12314 TestCompletionCallback callback;
12315
12316 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612317 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112318
12319 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012320 HttpServerProperties* http_server_properties =
12321 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412322 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912323 http_server_properties
12324 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12325 .empty());
bnce3dd56f2016-06-01 10:37:1112326
tfarina42834112016-09-22 13:38:2012327 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112328 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12329 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1112330
bnc691fda62016-08-12 00:43:1612331 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1112332 ASSERT_TRUE(response);
12333 ASSERT_TRUE(response->headers);
12334 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12335 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212336 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1112337
12338 std::string response_data;
bnc691fda62016-08-12 00:43:1612339 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1112340 EXPECT_EQ("hello world", response_data);
12341
zhongyic4de03032017-05-19 04:07:3412342 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912343 http_server_properties
12344 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12345 .empty());
bnce3dd56f2016-06-01 10:37:1112346}
12347
bnca86731e2017-04-17 12:31:2812348// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2512349// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0112350TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2512351 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2812352 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4512353
bnc8bef8da22016-05-30 01:28:2512354 HttpRequestInfo request;
12355 request.method = "GET";
bncb26024382016-06-29 02:39:4512356 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2512357 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012358 request.traffic_annotation =
12359 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2512360
12361 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12362 StaticSocketDataProvider first_data;
12363 first_data.set_connect_data(mock_connect);
12364 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512365 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612366 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512367 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2512368
12369 MockRead data_reads[] = {
12370 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12371 MockRead(ASYNC, OK),
12372 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112373 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2512374 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12375
12376 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12377
bnc525e175a2016-06-20 12:36:4012378 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2512379 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112380 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
12381 444);
bnc8bef8da22016-05-30 01:28:2512382 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112383 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712384 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12385 alternative_service, expiration);
bnc8bef8da22016-05-30 01:28:2512386
bnc691fda62016-08-12 00:43:1612387 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2512388 TestCompletionCallback callback;
12389
tfarina42834112016-09-22 13:38:2012390 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2512391 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112392 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2512393}
12394
bnce3dd56f2016-06-01 10:37:1112395// Regression test for https://crbug.com/615497:
12396// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0112397TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112398 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1112399 HttpRequestInfo request;
12400 request.method = "GET";
12401 request.url = GURL("http://www.example.org/");
12402 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012403 request.traffic_annotation =
12404 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112405
12406 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12407 StaticSocketDataProvider first_data;
12408 first_data.set_connect_data(mock_connect);
12409 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
12410
12411 MockRead data_reads[] = {
12412 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12413 MockRead(ASYNC, OK),
12414 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112415 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112416 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12417
12418 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12419
bnc525e175a2016-06-20 12:36:4012420 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1112421 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112422 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1112423 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112424 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712425 url::SchemeHostPort(request.url), NetworkIsolationKey(),
12426 alternative_service, expiration);
bnce3dd56f2016-06-01 10:37:1112427
bnc691fda62016-08-12 00:43:1612428 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112429 TestCompletionCallback callback;
12430
tfarina42834112016-09-22 13:38:2012431 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1112432 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112433 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1112434}
12435
bncd16676a2016-07-20 16:23:0112436TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0812437 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0912438 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012439 HttpServerProperties* http_server_properties =
12440 session->http_server_properties();
bncb26024382016-06-29 02:39:4512441 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2112442 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0812443 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112444 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712445 test_server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212446 session->params().quic_params.supported_versions);
Matt Menke3233d8f22019-08-20 21:01:4912447 EXPECT_EQ(1u,
12448 http_server_properties
12449 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12450 .size());
bnc4f575852015-10-14 18:35:0812451
12452 // Send a clear header.
12453 MockRead data_reads[] = {
12454 MockRead("HTTP/1.1 200 OK\r\n"),
12455 MockRead("Alt-Svc: clear\r\n"),
12456 MockRead("\r\n"),
12457 MockRead("hello world"),
12458 MockRead(SYNCHRONOUS, OK),
12459 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112460 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0812461 session_deps_.socket_factory->AddSocketDataProvider(&data);
12462
bncb26024382016-06-29 02:39:4512463 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912464 ssl.ssl_info.cert =
12465 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12466 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12468
bnc4f575852015-10-14 18:35:0812469 HttpRequestInfo request;
12470 request.method = "GET";
bncb26024382016-06-29 02:39:4512471 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012472 request.traffic_annotation =
12473 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0812474
12475 TestCompletionCallback callback;
12476
bnc691fda62016-08-12 00:43:1612477 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0812478
tfarina42834112016-09-22 13:38:2012479 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112480 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0812481
bnc691fda62016-08-12 00:43:1612482 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212483 ASSERT_TRUE(response);
12484 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0812485 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12486 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212487 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0812488
12489 std::string response_data;
bnc691fda62016-08-12 00:43:1612490 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0812491 EXPECT_EQ("hello world", response_data);
12492
zhongyic4de03032017-05-19 04:07:3412493 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912494 http_server_properties
12495 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12496 .empty());
bnc4f575852015-10-14 18:35:0812497}
12498
bncd16676a2016-07-20 16:23:0112499TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5212500 MockRead data_reads[] = {
12501 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312502 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
12503 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5212504 MockRead("hello world"),
12505 MockRead(SYNCHRONOUS, OK),
12506 };
12507
12508 HttpRequestInfo request;
12509 request.method = "GET";
bncb26024382016-06-29 02:39:4512510 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012511 request.traffic_annotation =
12512 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212513
Ryan Sleevib8d7ea02018-05-07 20:01:0112514 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212515 session_deps_.socket_factory->AddSocketDataProvider(&data);
12516
bncb26024382016-06-29 02:39:4512517 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912518 ssl.ssl_info.cert =
12519 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12520 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512521 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12522
bncc958faa2015-07-31 18:14:5212523 TestCompletionCallback callback;
12524
danakj1fd259a02016-04-16 03:17:0912525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612526 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212527
tfarina42834112016-09-22 13:38:2012528 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112529 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212530
bncb26024382016-06-29 02:39:4512531 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4012532 HttpServerProperties* http_server_properties =
12533 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412534 EXPECT_TRUE(
Matt Menke3233d8f22019-08-20 21:01:4912535 http_server_properties
12536 ->GetAlternativeServiceInfos(test_server, NetworkIsolationKey())
12537 .empty());
bncc958faa2015-07-31 18:14:5212538
robpercival214763f2016-07-01 23:27:0112539 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212540
bnc691fda62016-08-12 00:43:1612541 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212542 ASSERT_TRUE(response);
12543 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212544 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12545 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212546 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212547
12548 std::string response_data;
bnc691fda62016-08-12 00:43:1612549 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212550 EXPECT_EQ("hello world", response_data);
12551
zhongyic4de03032017-05-19 04:07:3412552 AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912553 http_server_properties->GetAlternativeServiceInfos(test_server,
12554 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412555 ASSERT_EQ(2u, alternative_service_info_vector.size());
12556
12557 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
12558 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412559 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412560 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
12561 1234);
12562 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5412563 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5212564}
12565
bncd16676a2016-07-20 16:23:0112566TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612567 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212568 HostPortPair alternative("alternative.example.org", 443);
12569 std::string origin_url = "https://origin.example.org:443";
12570 std::string alternative_url = "https://alternative.example.org:443";
12571
12572 // Negotiate HTTP/1.1 with alternative.example.org.
12573 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612574 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212575 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12576
12577 // HTTP/1.1 data for request.
12578 MockWrite http_writes[] = {
12579 MockWrite("GET / HTTP/1.1\r\n"
12580 "Host: alternative.example.org\r\n"
12581 "Connection: keep-alive\r\n\r\n"),
12582 };
12583
12584 MockRead http_reads[] = {
12585 MockRead("HTTP/1.1 200 OK\r\n"
12586 "Content-Type: text/html; charset=iso-8859-1\r\n"
12587 "Content-Length: 40\r\n\r\n"
12588 "first HTTP/1.1 response from alternative"),
12589 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112590 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212591 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12592
12593 StaticSocketDataProvider data_refused;
12594 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12595 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12596
zhongyi3d4a55e72016-04-22 20:36:4612597 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0912598 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012599 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212600 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112601 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0212602 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112603 http_server_properties->SetQuicAlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712604 server, NetworkIsolationKey(), alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212605 HttpNetworkSession::Params().quic_params.supported_versions);
zhongyi48704c182015-12-07 07:52:0212606 // Mark the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0512607 http_server_properties->MarkAlternativeServiceBroken(alternative_service,
12608 NetworkIsolationKey());
zhongyi48704c182015-12-07 07:52:0212609
zhongyi48704c182015-12-07 07:52:0212610 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612611 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212612 request.method = "GET";
12613 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012614 request.traffic_annotation =
12615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12616
zhongyi48704c182015-12-07 07:52:0212617 TestCompletionCallback callback;
12618 NetErrorDetails details;
12619 EXPECT_FALSE(details.quic_broken);
12620
tfarina42834112016-09-22 13:38:2012621 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612622 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212623 EXPECT_TRUE(details.quic_broken);
12624}
12625
bncd16676a2016-07-20 16:23:0112626TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612627 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212628 HostPortPair alternative1("alternative1.example.org", 443);
12629 HostPortPair alternative2("alternative2.example.org", 443);
12630 std::string origin_url = "https://origin.example.org:443";
12631 std::string alternative_url1 = "https://alternative1.example.org:443";
12632 std::string alternative_url2 = "https://alternative2.example.org:443";
12633
12634 // Negotiate HTTP/1.1 with alternative1.example.org.
12635 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612636 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12638
12639 // HTTP/1.1 data for request.
12640 MockWrite http_writes[] = {
12641 MockWrite("GET / HTTP/1.1\r\n"
12642 "Host: alternative1.example.org\r\n"
12643 "Connection: keep-alive\r\n\r\n"),
12644 };
12645
12646 MockRead http_reads[] = {
12647 MockRead("HTTP/1.1 200 OK\r\n"
12648 "Content-Type: text/html; charset=iso-8859-1\r\n"
12649 "Content-Length: 40\r\n\r\n"
12650 "first HTTP/1.1 response from alternative1"),
12651 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112652 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212653 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12654
12655 StaticSocketDataProvider data_refused;
12656 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12657 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12658
danakj1fd259a02016-04-16 03:17:0912659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012660 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212661 session->http_server_properties();
12662
zhongyi3d4a55e72016-04-22 20:36:4612663 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0212664 AlternativeServiceInfoVector alternative_service_info_vector;
12665 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12666
bnc3472afd2016-11-17 15:27:2112667 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2112668 alternative_service_info_vector.push_back(
12669 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12670 alternative_service1, expiration,
Nick Harper72ade192019-07-17 03:30:4212671 session->params().quic_params.supported_versions));
bnc3472afd2016-11-17 15:27:2112672 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2112673 alternative_service_info_vector.push_back(
12674 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12675 alternative_service2, expiration,
Nick Harper72ade192019-07-17 03:30:4212676 session->params().quic_params.supported_versions));
zhongyi48704c182015-12-07 07:52:0212677
12678 http_server_properties->SetAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:4912679 server, NetworkIsolationKey(), alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0212680
12681 // Mark one of the QUIC alternative service as broken.
Matt Menkeb32ba5122019-09-10 19:17:0512682 http_server_properties->MarkAlternativeServiceBroken(alternative_service1,
12683 NetworkIsolationKey());
Matt Menke3233d8f22019-08-20 21:01:4912684 EXPECT_EQ(2u, http_server_properties
12685 ->GetAlternativeServiceInfos(server, NetworkIsolationKey())
12686 .size());
zhongyi48704c182015-12-07 07:52:0212687
zhongyi48704c182015-12-07 07:52:0212688 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612689 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212690 request.method = "GET";
12691 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012692 request.traffic_annotation =
12693 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12694
zhongyi48704c182015-12-07 07:52:0212695 TestCompletionCallback callback;
12696 NetErrorDetails details;
12697 EXPECT_FALSE(details.quic_broken);
12698
tfarina42834112016-09-22 13:38:2012699 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612700 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212701 EXPECT_FALSE(details.quic_broken);
12702}
12703
bncd16676a2016-07-20 16:23:0112704TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4212705 HttpRequestInfo request;
12706 request.method = "GET";
bncb26024382016-06-29 02:39:4512707 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012708 request.traffic_annotation =
12709 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4212710
[email protected]d973e99a2012-02-17 21:02:3612711 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4212712 StaticSocketDataProvider first_data;
12713 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712714 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512715 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612716 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512717 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4212718
12719 MockRead data_reads[] = {
12720 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12721 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612722 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4212723 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112724 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712725 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4212726
danakj1fd259a02016-04-16 03:17:0912727 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4212728
bnc525e175a2016-06-20 12:36:4012729 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312730 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4612731 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1112732 // Port must be < 1024, or the header will be ignored (since initial port was
12733 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2112734 // Port is ignored by MockConnect anyway.
12735 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12736 666);
bnc7dc7e1b42015-07-28 14:43:1212737 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112738 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712739 server, NetworkIsolationKey(), alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4212740
bnc691fda62016-08-12 00:43:1612741 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112742 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4212743
tfarina42834112016-09-22 13:38:2012744 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112745 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12746 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4212747
bnc691fda62016-08-12 00:43:1612748 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212749 ASSERT_TRUE(response);
12750 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4212751 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12752
12753 std::string response_data;
bnc691fda62016-08-12 00:43:1612754 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4212755 EXPECT_EQ("hello world", response_data);
12756
zhongyic4de03032017-05-19 04:07:3412757 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:4912758 http_server_properties->GetAlternativeServiceInfos(server,
12759 NetworkIsolationKey());
zhongyic4de03032017-05-19 04:07:3412760 ASSERT_EQ(1u, alternative_service_info_vector.size());
12761 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412762 alternative_service_info_vector[0].alternative_service());
Matt Menkeb32ba5122019-09-10 19:17:0512763 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
12764 alternative_service, NetworkIsolationKey()));
[email protected]564b4912010-03-09 16:30:4212765}
12766
bnc55ff9da2015-08-19 18:42:3512767// Ensure that we are not allowed to redirect traffic via an alternate protocol
12768// to an unrestricted (port >= 1024) when the original traffic was on a
12769// restricted port (port < 1024). Ensure that we can redirect in all other
12770// cases.
bncd16676a2016-07-20 16:23:0112771TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1112772 HttpRequestInfo restricted_port_request;
12773 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512774 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112775 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012776 restricted_port_request.traffic_annotation =
12777 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112778
[email protected]d973e99a2012-02-17 21:02:3612779 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112780 StaticSocketDataProvider first_data;
12781 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712782 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112783
12784 MockRead data_reads[] = {
12785 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12786 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612787 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112788 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112789 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712790 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512791 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612792 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512793 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112794
danakj1fd259a02016-04-16 03:17:0912795 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112796
bnc525e175a2016-06-20 12:36:4012797 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312798 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112799 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112800 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12801 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212802 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112803 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712804 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12805 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112806
bnc691fda62016-08-12 00:43:1612807 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112808 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112809
tfarina42834112016-09-22 13:38:2012810 int rv = trans.Start(&restricted_port_request, callback.callback(),
12811 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112812 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112813 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0112814 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1912815}
[email protected]3912662a32011-10-04 00:51:1112816
bnc55ff9da2015-08-19 18:42:3512817// Ensure that we are allowed to redirect traffic via an alternate protocol to
12818// an unrestricted (port >= 1024) when the original traffic was on a restricted
12819// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0112820TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0712821 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1912822
12823 HttpRequestInfo restricted_port_request;
12824 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512825 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1912826 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012827 restricted_port_request.traffic_annotation =
12828 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1912829
12830 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12831 StaticSocketDataProvider first_data;
12832 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712833 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1912834
12835 MockRead data_reads[] = {
12836 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12837 MockRead("hello world"),
12838 MockRead(ASYNC, OK),
12839 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112840 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712841 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512842 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612843 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1912845
danakj1fd259a02016-04-16 03:17:0912846 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1912847
bnc525e175a2016-06-20 12:36:4012848 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1912849 session->http_server_properties();
12850 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112851 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12852 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212853 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112854 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712855 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12856 alternative_service, expiration);
[email protected]c54c6962013-02-01 04:53:1912857
bnc691fda62016-08-12 00:43:1612858 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1912859 TestCompletionCallback callback;
12860
tfarina42834112016-09-22 13:38:2012861 EXPECT_EQ(ERR_IO_PENDING,
12862 trans.Start(&restricted_port_request, callback.callback(),
12863 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1912864 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0112865 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112866}
12867
bnc55ff9da2015-08-19 18:42:3512868// Ensure that we are not allowed to redirect traffic via an alternate protocol
12869// to an unrestricted (port >= 1024) when the original traffic was on a
12870// restricted port (port < 1024). Ensure that we can redirect in all other
12871// cases.
bncd16676a2016-07-20 16:23:0112872TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1112873 HttpRequestInfo restricted_port_request;
12874 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512875 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112876 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012877 restricted_port_request.traffic_annotation =
12878 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112879
[email protected]d973e99a2012-02-17 21:02:3612880 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112881 StaticSocketDataProvider first_data;
12882 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712883 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112884
12885 MockRead data_reads[] = {
12886 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12887 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612888 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112889 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112890 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712891 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112892
bncb26024382016-06-29 02:39:4512893 SSLSocketDataProvider ssl(ASYNC, OK);
12894 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12895
danakj1fd259a02016-04-16 03:17:0912896 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112897
bnc525e175a2016-06-20 12:36:4012898 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312899 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112900 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112901 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12902 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212903 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112904 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712905 url::SchemeHostPort(restricted_port_request.url), NetworkIsolationKey(),
12906 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112907
bnc691fda62016-08-12 00:43:1612908 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112909 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112910
tfarina42834112016-09-22 13:38:2012911 int rv = trans.Start(&restricted_port_request, callback.callback(),
12912 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112913 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112914 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112915 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112916}
12917
bnc55ff9da2015-08-19 18:42:3512918// Ensure that we are not allowed to redirect traffic via an alternate protocol
12919// to an unrestricted (port >= 1024) when the original traffic was on a
12920// restricted port (port < 1024). Ensure that we can redirect in all other
12921// cases.
bncd16676a2016-07-20 16:23:0112922TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1112923 HttpRequestInfo unrestricted_port_request;
12924 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512925 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112926 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012927 unrestricted_port_request.traffic_annotation =
12928 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112929
[email protected]d973e99a2012-02-17 21:02:3612930 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112931 StaticSocketDataProvider first_data;
12932 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712933 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112934
12935 MockRead data_reads[] = {
12936 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12937 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612938 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112939 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112940 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712941 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512942 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612943 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112945
danakj1fd259a02016-04-16 03:17:0912946 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112947
bnc525e175a2016-06-20 12:36:4012948 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312949 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112950 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112951 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12952 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212953 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112954 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0712955 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
12956 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1112957
bnc691fda62016-08-12 00:43:1612958 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112959 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112960
bnc691fda62016-08-12 00:43:1612961 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012962 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112963 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112964 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112965 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112966}
12967
bnc55ff9da2015-08-19 18:42:3512968// Ensure that we are not allowed to redirect traffic via an alternate protocol
12969// to an unrestricted (port >= 1024) when the original traffic was on a
12970// restricted port (port < 1024). Ensure that we can redirect in all other
12971// cases.
bncd16676a2016-07-20 16:23:0112972TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1112973 HttpRequestInfo unrestricted_port_request;
12974 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512975 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112976 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012977 unrestricted_port_request.traffic_annotation =
12978 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112979
[email protected]d973e99a2012-02-17 21:02:3612980 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112981 StaticSocketDataProvider first_data;
12982 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712983 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112984
12985 MockRead data_reads[] = {
12986 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12987 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612988 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112989 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112990 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712991 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112992
bncb26024382016-06-29 02:39:4512993 SSLSocketDataProvider ssl(ASYNC, OK);
12994 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12995
danakj1fd259a02016-04-16 03:17:0912996 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112997
bnc525e175a2016-06-20 12:36:4012998 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312999 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2213000 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2113001 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13002 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1213003 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113004 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713005 url::SchemeHostPort(unrestricted_port_request.url), NetworkIsolationKey(),
13006 alternative_service, expiration);
[email protected]3912662a32011-10-04 00:51:1113007
bnc691fda62016-08-12 00:43:1613008 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4113009 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1113010
bnc691fda62016-08-12 00:43:1613011 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2013012 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113013 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1113014 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0113015 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1113016}
13017
bnc55ff9da2015-08-19 18:42:3513018// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2113019// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
13020// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0113021TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0213022 HttpRequestInfo request;
13023 request.method = "GET";
bncce36dca22015-04-21 22:11:2313024 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013025 request.traffic_annotation =
13026 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0213027
13028 // The alternate protocol request will error out before we attempt to connect,
13029 // so only the standard HTTP request will try to connect.
13030 MockRead data_reads[] = {
13031 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
13032 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0613033 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0213034 };
Ryan Sleevib8d7ea02018-05-07 20:01:0113035 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713036 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0213037
danakj1fd259a02016-04-16 03:17:0913038 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0213039
bnc525e175a2016-06-20 12:36:4013040 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0213041 session->http_server_properties();
13042 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2113043 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
13044 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1213045 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113046 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713047 url::SchemeHostPort(request.url), NetworkIsolationKey(),
13048 alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0213049
bnc691fda62016-08-12 00:43:1613050 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0213051 TestCompletionCallback callback;
13052
tfarina42834112016-09-22 13:38:2013053 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0213055 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0113056 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213057
bnc691fda62016-08-12 00:43:1613058 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5213059 ASSERT_TRUE(response);
13060 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0213061 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13062
13063 std::string response_data;
bnc691fda62016-08-12 00:43:1613064 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0213065 EXPECT_EQ("hello world", response_data);
13066}
13067
bncd16676a2016-07-20 16:23:0113068TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5413069 HttpRequestInfo request;
13070 request.method = "GET";
bncb26024382016-06-29 02:39:4513071 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013072 request.traffic_annotation =
13073 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413074
13075 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213076 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313077 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213078 MockRead("\r\n"),
13079 MockRead("hello world"),
13080 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13081 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5413082
Ryan Sleevib8d7ea02018-05-07 20:01:0113083 StaticSocketDataProvider first_transaction(data_reads,
13084 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713085 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513086 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613087 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513088 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413089
bnc032658ba2016-09-26 18:17:1513090 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413091
Ryan Hamilton0239aac2018-05-19 00:03:1313092 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513093 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113094 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413095
Raul Tambre94493c652019-03-11 17:18:3513096 spdy::SpdySerializedFrame resp(
13097 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313098 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413099 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113100 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413101 };
13102
Ryan Sleevib8d7ea02018-05-07 20:01:0113103 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713104 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413105
[email protected]d973e99a2012-02-17 21:02:3613106 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113107 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513108 hanging_non_alternate_protocol_socket.set_connect_data(
13109 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713110 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513111 &hanging_non_alternate_protocol_socket);
13112
[email protected]49639fa2011-12-20 23:22:4113113 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413114
danakj1fd259a02016-04-16 03:17:0913115 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813116 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913117 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413118
tfarina42834112016-09-22 13:38:2013119 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113120 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13121 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413122
13123 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213124 ASSERT_TRUE(response);
13125 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413126 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13127
13128 std::string response_data;
robpercival214763f2016-07-01 23:27:0113129 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413130 EXPECT_EQ("hello world", response_data);
13131
bnc87dcefc2017-05-25 12:47:5813132 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913133 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413134
tfarina42834112016-09-22 13:38:2013135 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113136 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13137 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413138
13139 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213140 ASSERT_TRUE(response);
13141 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213142 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313143 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213144 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413145
robpercival214763f2016-07-01 23:27:0113146 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413147 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5413148}
13149
bncd16676a2016-07-20 16:23:0113150TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5513151 HttpRequestInfo request;
13152 request.method = "GET";
bncb26024382016-06-29 02:39:4513153 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013154 request.traffic_annotation =
13155 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513156
bncb26024382016-06-29 02:39:4513157 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5513158 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213159 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313160 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213161 MockRead("\r\n"),
13162 MockRead("hello world"),
13163 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13164 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513165 };
13166
Ryan Sleevib8d7ea02018-05-07 20:01:0113167 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4513168 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5513169
bncb26024382016-06-29 02:39:4513170 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913171 ssl_http11.ssl_info.cert =
13172 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13173 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4513174 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
13175
13176 // Second transaction starts an alternative and a non-alternative Job.
13177 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3613178 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113179 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1813180 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1813181 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
13182
Ryan Sleevib8d7ea02018-05-07 20:01:0113183 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1813184 hanging_socket2.set_connect_data(never_finishing_connect);
13185 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5513186
bncb26024382016-06-29 02:39:4513187 // Third transaction starts an alternative and a non-alternative job.
13188 // The non-alternative job hangs, but the alternative one succeeds.
13189 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1313190 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4513191 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1313192 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4513193 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5513194 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113195 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5513196 };
Raul Tambre94493c652019-03-11 17:18:3513197 spdy::SpdySerializedFrame resp1(
13198 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313199 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3513200 spdy::SpdySerializedFrame resp2(
13201 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1313202 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5513203 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113204 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
13205 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1313206 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5513207 };
13208
Ryan Sleevib8d7ea02018-05-07 20:01:0113209 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713210 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5513211
bnc032658ba2016-09-26 18:17:1513212 AddSSLSocketData();
bncb26024382016-06-29 02:39:4513213
Ryan Sleevib8d7ea02018-05-07 20:01:0113214 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1813215 hanging_socket3.set_connect_data(never_finishing_connect);
13216 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5513217
danakj1fd259a02016-04-16 03:17:0913218 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4113219 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5013220 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513221
tfarina42834112016-09-22 13:38:2013222 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113223 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13224 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513225
13226 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213227 ASSERT_TRUE(response);
13228 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513229 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13230
13231 std::string response_data;
robpercival214763f2016-07-01 23:27:0113232 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513233 EXPECT_EQ("hello world", response_data);
13234
[email protected]49639fa2011-12-20 23:22:4113235 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5013236 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013237 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113238 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513239
[email protected]49639fa2011-12-20 23:22:4113240 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5013241 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2013242 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113243 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5513244
robpercival214763f2016-07-01 23:27:0113245 EXPECT_THAT(callback2.WaitForResult(), IsOk());
13246 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513247
13248 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213249 ASSERT_TRUE(response);
13250 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213251 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513252 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213253 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113254 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513255 EXPECT_EQ("hello!", response_data);
13256
13257 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5213258 ASSERT_TRUE(response);
13259 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213260 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513261 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213262 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113263 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513264 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5513265}
13266
bncd16676a2016-07-20 16:23:0113267TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5313268 session_deps_.host_resolver->set_synchronous_mode(true);
13269
[email protected]2d6728692011-03-12 01:39:5513270 HttpRequestInfo request;
13271 request.method = "GET";
bncb26024382016-06-29 02:39:4513272 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013273 request.traffic_annotation =
13274 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513275
13276 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213277 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313278 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213279 MockRead("\r\n"),
13280 MockRead("hello world"),
13281 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13282 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513283 };
13284
Ryan Sleevib8d7ea02018-05-07 20:01:0113285 StaticSocketDataProvider first_transaction(data_reads,
13286 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713287 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513288
[email protected]8ddf8322012-02-23 18:08:0613289 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913290 ssl.ssl_info.cert =
13291 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13292 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713293 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513294
[email protected]d973e99a2012-02-17 21:02:3613295 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113296 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513297 hanging_alternate_protocol_socket.set_connect_data(
13298 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713299 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513300 &hanging_alternate_protocol_socket);
13301
bncb26024382016-06-29 02:39:4513302 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0113303 StaticSocketDataProvider second_transaction(data_reads,
13304 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1813305 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4513306 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513307
[email protected]49639fa2011-12-20 23:22:4113308 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5513309
danakj1fd259a02016-04-16 03:17:0913310 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813311 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913312 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513313
tfarina42834112016-09-22 13:38:2013314 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113315 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13316 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513317
13318 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213319 ASSERT_TRUE(response);
13320 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513321 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13322
13323 std::string response_data;
robpercival214763f2016-07-01 23:27:0113324 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513325 EXPECT_EQ("hello world", response_data);
13326
bnc87dcefc2017-05-25 12:47:5813327 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913328 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513329
tfarina42834112016-09-22 13:38:2013330 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113331 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13332 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513333
13334 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213335 ASSERT_TRUE(response);
13336 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513337 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13338 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213339 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5513340
robpercival214763f2016-07-01 23:27:0113341 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513342 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5513343}
13344
bnc2e884782016-08-11 19:45:1913345// Test that proxy is resolved using the origin url,
13346// regardless of the alternative server.
13347TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
13348 // Configure proxy to bypass www.example.org, which is the origin URL.
13349 ProxyConfig proxy_config;
13350 proxy_config.proxy_rules().ParseFromString("myproxy:70");
13351 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4913352 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
13353 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1913354
13355 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1913356 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1913357 &capturing_proxy_resolver);
13358
13359 TestNetLog net_log;
13360
Bence Béky53a5aef2018-03-29 21:54:1213361 session_deps_.proxy_resolution_service =
13362 std::make_unique<ProxyResolutionService>(
13363 std::move(proxy_config_service), std::move(proxy_resolver_factory),
13364 &net_log);
bnc2e884782016-08-11 19:45:1913365
13366 session_deps_.net_log = &net_log;
13367
13368 // Configure alternative service with a hostname that is not bypassed by the
13369 // proxy.
13370 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13371 HttpServerProperties* http_server_properties =
13372 session->http_server_properties();
13373 url::SchemeHostPort server("https", "www.example.org", 443);
13374 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2113375 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1913376 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113377 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0713378 server, NetworkIsolationKey(), alternative_service, expiration);
bnc2e884782016-08-11 19:45:1913379
13380 // Non-alternative job should hang.
13381 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113382 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1913383 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
13384 session_deps_.socket_factory->AddSocketDataProvider(
13385 &hanging_alternate_protocol_socket);
13386
bnc032658ba2016-09-26 18:17:1513387 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1913388
13389 HttpRequestInfo request;
13390 request.method = "GET";
13391 request.url = GURL("https://www.example.org/");
13392 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013393 request.traffic_annotation =
13394 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1913395
Ryan Hamilton0239aac2018-05-19 00:03:1313396 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1913397 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
13398
13399 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
13400
Ryan Hamilton0239aac2018-05-19 00:03:1313401 spdy::SpdySerializedFrame resp(
13402 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
13403 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1913404 MockRead spdy_reads[] = {
13405 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
13406 };
13407
Ryan Sleevib8d7ea02018-05-07 20:01:0113408 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1913409 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
13410
13411 TestCompletionCallback callback;
13412
13413 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13414
tfarina42834112016-09-22 13:38:2013415 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1913416 EXPECT_THAT(callback.GetResult(rv), IsOk());
13417
13418 const HttpResponseInfo* response = trans.GetResponseInfo();
13419 ASSERT_TRUE(response);
13420 ASSERT_TRUE(response->headers);
13421 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
13422 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213423 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1913424
13425 std::string response_data;
13426 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13427 EXPECT_EQ("hello!", response_data);
13428
13429 // Origin host bypasses proxy, no resolution should have happened.
13430 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
13431}
13432
bncd16676a2016-07-20 16:23:0113433TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1113434 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4213435 proxy_config.set_auto_detect(true);
13436 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1113437
sammc5dd160c2015-04-02 02:43:1313438 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4913439 session_deps_.proxy_resolution_service =
13440 std::make_unique<ProxyResolutionService>(
13441 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
13442 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
13443 std::make_unique<CapturingProxyResolverFactory>(
13444 &capturing_proxy_resolver),
13445 nullptr);
vishal.b62985ca92015-04-17 08:45:5113446 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0713447 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1113448
13449 HttpRequestInfo request;
13450 request.method = "GET";
bncb26024382016-06-29 02:39:4513451 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013452 request.traffic_annotation =
13453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1113454
13455 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213456 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313457 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213458 MockRead("\r\n"),
13459 MockRead("hello world"),
13460 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13461 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1113462 };
13463
Ryan Sleevib8d7ea02018-05-07 20:01:0113464 StaticSocketDataProvider first_transaction(data_reads,
13465 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713466 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513467 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613468 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513469 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1113470
bnc032658ba2016-09-26 18:17:1513471 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1113472
Ryan Hamilton0239aac2018-05-19 00:03:1313473 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513474 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1113475 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313476 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2513477 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13478 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1313479 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4113480 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1113481 };
13482
[email protected]d911f1b2010-05-05 22:39:4213483 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
13484
Raul Tambre94493c652019-03-11 17:18:3513485 spdy::SpdySerializedFrame resp(
13486 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313487 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1113488 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113489 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
13490 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1113491 };
13492
Ryan Sleevib8d7ea02018-05-07 20:01:0113493 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713494 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1113495
[email protected]d973e99a2012-02-17 21:02:3613496 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113497 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513498 hanging_non_alternate_protocol_socket.set_connect_data(
13499 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713500 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513501 &hanging_non_alternate_protocol_socket);
13502
[email protected]49639fa2011-12-20 23:22:4113503 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1113504
danakj1fd259a02016-04-16 03:17:0913505 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813506 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913507 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113508
tfarina42834112016-09-22 13:38:2013509 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4113510 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13511 EXPECT_THAT(callback.WaitForResult(), IsOk());
13512
13513 const HttpResponseInfo* response = trans->GetResponseInfo();
13514 ASSERT_TRUE(response);
13515 ASSERT_TRUE(response->headers);
13516 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
13517 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213518 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4113519
13520 std::string response_data;
13521 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
13522 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1113523
bnc87dcefc2017-05-25 12:47:5813524 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913525 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113526
tfarina42834112016-09-22 13:38:2013527 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113528 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13529 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1113530
mmenkea2dcd3bf2016-08-16 21:49:4113531 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213532 ASSERT_TRUE(response);
13533 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213534 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313535 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213536 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1113537
robpercival214763f2016-07-01 23:27:0113538 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1113539 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4513540 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
13541 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313542 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2313543 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313544 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1113545
[email protected]029c83b62013-01-24 05:28:2013546 LoadTimingInfo load_timing_info;
13547 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
13548 TestLoadTimingNotReusedWithPac(load_timing_info,
13549 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1113550}
[email protected]631f1322010-04-30 17:59:1113551
bncd16676a2016-07-20 16:23:0113552TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4813553 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5413554 HttpRequestInfo request;
13555 request.method = "GET";
bncb26024382016-06-29 02:39:4513556 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013557 request.traffic_annotation =
13558 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413559
13560 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213561 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313562 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213563 MockRead("\r\n"),
13564 MockRead("hello world"),
13565 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5413566 };
13567
Ryan Sleevib8d7ea02018-05-07 20:01:0113568 StaticSocketDataProvider first_transaction(data_reads,
13569 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713570 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513571 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613572 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513573 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413574
bnc032658ba2016-09-26 18:17:1513575 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413576
Ryan Hamilton0239aac2018-05-19 00:03:1313577 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513578 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113579 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413580
Raul Tambre94493c652019-03-11 17:18:3513581 spdy::SpdySerializedFrame resp(
13582 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313583 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413584 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113585 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413586 };
13587
Ryan Sleevib8d7ea02018-05-07 20:01:0113588 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713589 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413590
[email protected]83039bb2011-12-09 18:43:5513591 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413592
danakj1fd259a02016-04-16 03:17:0913593 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5413594
bnc87dcefc2017-05-25 12:47:5813595 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913596 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413597
tfarina42834112016-09-22 13:38:2013598 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113599 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13600 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413601
13602 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213603 ASSERT_TRUE(response);
13604 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413605 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13606
13607 std::string response_data;
robpercival214763f2016-07-01 23:27:0113608 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413609 EXPECT_EQ("hello world", response_data);
13610
13611 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2513612 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4013613 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1113614 PRIVACY_MODE_DISABLED,
13615 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2713616 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5213617 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3813618
bnc87dcefc2017-05-25 12:47:5813619 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913620 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413621
tfarina42834112016-09-22 13:38:2013622 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113623 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13624 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413625
13626 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213627 ASSERT_TRUE(response);
13628 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213629 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313630 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213631 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413632
robpercival214763f2016-07-01 23:27:0113633 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413634 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4213635}
13636
[email protected]044de0642010-06-17 10:42:1513637// GenerateAuthToken is a mighty big test.
13638// It tests all permutation of GenerateAuthToken behavior:
13639// - Synchronous and Asynchronous completion.
13640// - OK or error on completion.
13641// - Direct connection, non-authenticating proxy, and authenticating proxy.
13642// - HTTP or HTTPS backend (to include proxy tunneling).
13643// - Non-authenticating and authenticating backend.
13644//
[email protected]fe3b7dc2012-02-03 19:52:0913645// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1513646// problems generating an auth token for an authenticating proxy, we don't
13647// need to test all permutations of the backend server).
13648//
13649// The test proceeds by going over each of the configuration cases, and
13650// potentially running up to three rounds in each of the tests. The TestConfig
13651// specifies both the configuration for the test as well as the expectations
13652// for the results.
bncd16676a2016-07-20 16:23:0113653TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5013654 static const char kServer[] = "http://www.example.com";
13655 static const char kSecureServer[] = "https://www.example.com";
13656 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1513657
13658 enum AuthTiming {
13659 AUTH_NONE,
13660 AUTH_SYNC,
13661 AUTH_ASYNC,
13662 };
13663
13664 const MockWrite kGet(
13665 "GET / HTTP/1.1\r\n"
13666 "Host: www.example.com\r\n"
13667 "Connection: keep-alive\r\n\r\n");
13668 const MockWrite kGetProxy(
13669 "GET http://www.example.com/ HTTP/1.1\r\n"
13670 "Host: www.example.com\r\n"
13671 "Proxy-Connection: keep-alive\r\n\r\n");
13672 const MockWrite kGetAuth(
13673 "GET / HTTP/1.1\r\n"
13674 "Host: www.example.com\r\n"
13675 "Connection: keep-alive\r\n"
13676 "Authorization: auth_token\r\n\r\n");
13677 const MockWrite kGetProxyAuth(
13678 "GET http://www.example.com/ HTTP/1.1\r\n"
13679 "Host: www.example.com\r\n"
13680 "Proxy-Connection: keep-alive\r\n"
13681 "Proxy-Authorization: auth_token\r\n\r\n");
13682 const MockWrite kGetAuthThroughProxy(
13683 "GET http://www.example.com/ HTTP/1.1\r\n"
13684 "Host: www.example.com\r\n"
13685 "Proxy-Connection: keep-alive\r\n"
13686 "Authorization: auth_token\r\n\r\n");
13687 const MockWrite kGetAuthWithProxyAuth(
13688 "GET http://www.example.com/ HTTP/1.1\r\n"
13689 "Host: www.example.com\r\n"
13690 "Proxy-Connection: keep-alive\r\n"
13691 "Proxy-Authorization: auth_token\r\n"
13692 "Authorization: auth_token\r\n\r\n");
13693 const MockWrite kConnect(
13694 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713695 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513696 "Proxy-Connection: keep-alive\r\n\r\n");
13697 const MockWrite kConnectProxyAuth(
13698 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713699 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513700 "Proxy-Connection: keep-alive\r\n"
13701 "Proxy-Authorization: auth_token\r\n\r\n");
13702
13703 const MockRead kSuccess(
13704 "HTTP/1.1 200 OK\r\n"
13705 "Content-Type: text/html; charset=iso-8859-1\r\n"
13706 "Content-Length: 3\r\n\r\n"
13707 "Yes");
13708 const MockRead kFailure(
13709 "Should not be called.");
13710 const MockRead kServerChallenge(
13711 "HTTP/1.1 401 Unauthorized\r\n"
13712 "WWW-Authenticate: Mock realm=server\r\n"
13713 "Content-Type: text/html; charset=iso-8859-1\r\n"
13714 "Content-Length: 14\r\n\r\n"
13715 "Unauthorized\r\n");
13716 const MockRead kProxyChallenge(
13717 "HTTP/1.1 407 Unauthorized\r\n"
13718 "Proxy-Authenticate: Mock realm=proxy\r\n"
13719 "Proxy-Connection: close\r\n"
13720 "Content-Type: text/html; charset=iso-8859-1\r\n"
13721 "Content-Length: 14\r\n\r\n"
13722 "Unauthorized\r\n");
13723 const MockRead kProxyConnected(
13724 "HTTP/1.1 200 Connection Established\r\n\r\n");
13725
13726 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
13727 // no constructors, but the C++ compiler on Windows warns about
13728 // unspecified data in compound literals. So, moved to using constructors,
13729 // and TestRound's created with the default constructor should not be used.
13730 struct TestRound {
13731 TestRound()
Raul Tambre94493c652019-03-11 17:18:3513732 : expected_rv(ERR_UNEXPECTED),
13733 extra_write(nullptr),
13734 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4313735 TestRound(const MockWrite& write_arg,
13736 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1513737 int expected_rv_arg)
13738 : write(write_arg),
13739 read(read_arg),
13740 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3513741 extra_write(nullptr),
13742 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1513743 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
13744 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0113745 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1513746 : write(write_arg),
13747 read(read_arg),
13748 expected_rv(expected_rv_arg),
13749 extra_write(extra_write_arg),
13750 extra_read(extra_read_arg) {
13751 }
13752 MockWrite write;
13753 MockRead read;
13754 int expected_rv;
13755 const MockWrite* extra_write;
13756 const MockRead* extra_read;
13757 };
13758
13759 static const int kNoSSL = 500;
13760
13761 struct TestConfig {
asanka463ca4262016-11-16 02:34:3113762 int line_number;
thestig9d3bb0c2015-01-24 00:49:5113763 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1513764 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3113765 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5113766 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1513767 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3113768 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1513769 int num_auth_rounds;
13770 int first_ssl_round;
asankae2257db2016-10-11 22:03:1613771 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1513772 } test_configs[] = {
asankac93076192016-10-03 15:46:0213773 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113774 {__LINE__,
13775 nullptr,
asankac93076192016-10-03 15:46:0213776 AUTH_NONE,
13777 OK,
13778 kServer,
13779 AUTH_NONE,
13780 OK,
13781 1,
13782 kNoSSL,
13783 {TestRound(kGet, kSuccess, OK)}},
13784 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113785 {__LINE__,
13786 nullptr,
asankac93076192016-10-03 15:46:0213787 AUTH_NONE,
13788 OK,
13789 kServer,
13790 AUTH_SYNC,
13791 OK,
13792 2,
13793 kNoSSL,
13794 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513795 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113796 {__LINE__,
13797 nullptr,
asankac93076192016-10-03 15:46:0213798 AUTH_NONE,
13799 OK,
13800 kServer,
13801 AUTH_SYNC,
13802 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613803 3,
13804 kNoSSL,
13805 {TestRound(kGet, kServerChallenge, OK),
13806 TestRound(kGet, kServerChallenge, OK),
13807 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113808 {__LINE__,
13809 nullptr,
asankae2257db2016-10-11 22:03:1613810 AUTH_NONE,
13811 OK,
13812 kServer,
13813 AUTH_SYNC,
13814 ERR_UNSUPPORTED_AUTH_SCHEME,
13815 2,
13816 kNoSSL,
13817 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113818 {__LINE__,
13819 nullptr,
asankae2257db2016-10-11 22:03:1613820 AUTH_NONE,
13821 OK,
13822 kServer,
13823 AUTH_SYNC,
13824 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
13825 2,
13826 kNoSSL,
13827 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113828 {__LINE__,
13829 kProxy,
asankae2257db2016-10-11 22:03:1613830 AUTH_SYNC,
13831 ERR_FAILED,
13832 kServer,
13833 AUTH_NONE,
13834 OK,
13835 2,
13836 kNoSSL,
13837 {TestRound(kGetProxy, kProxyChallenge, OK),
13838 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113839 {__LINE__,
13840 kProxy,
asankae2257db2016-10-11 22:03:1613841 AUTH_ASYNC,
13842 ERR_FAILED,
13843 kServer,
13844 AUTH_NONE,
13845 OK,
13846 2,
13847 kNoSSL,
13848 {TestRound(kGetProxy, kProxyChallenge, OK),
13849 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113850 {__LINE__,
13851 nullptr,
asankae2257db2016-10-11 22:03:1613852 AUTH_NONE,
13853 OK,
13854 kServer,
13855 AUTH_SYNC,
13856 ERR_FAILED,
asankac93076192016-10-03 15:46:0213857 2,
13858 kNoSSL,
13859 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613860 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113861 {__LINE__,
13862 nullptr,
asankae2257db2016-10-11 22:03:1613863 AUTH_NONE,
13864 OK,
13865 kServer,
13866 AUTH_ASYNC,
13867 ERR_FAILED,
13868 2,
13869 kNoSSL,
13870 {TestRound(kGet, kServerChallenge, OK),
13871 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113872 {__LINE__,
13873 nullptr,
asankac93076192016-10-03 15:46:0213874 AUTH_NONE,
13875 OK,
13876 kServer,
13877 AUTH_ASYNC,
13878 OK,
13879 2,
13880 kNoSSL,
13881 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513882 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113883 {__LINE__,
13884 nullptr,
asankac93076192016-10-03 15:46:0213885 AUTH_NONE,
13886 OK,
13887 kServer,
13888 AUTH_ASYNC,
13889 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613890 3,
asankac93076192016-10-03 15:46:0213891 kNoSSL,
13892 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613893 // The second round uses a HttpAuthHandlerMock that always succeeds.
13894 TestRound(kGet, kServerChallenge, OK),
13895 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213896 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113897 {__LINE__,
13898 kProxy,
asankac93076192016-10-03 15:46:0213899 AUTH_NONE,
13900 OK,
13901 kServer,
13902 AUTH_NONE,
13903 OK,
13904 1,
13905 kNoSSL,
13906 {TestRound(kGetProxy, kSuccess, OK)}},
13907 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113908 {__LINE__,
13909 kProxy,
asankac93076192016-10-03 15:46:0213910 AUTH_NONE,
13911 OK,
13912 kServer,
13913 AUTH_SYNC,
13914 OK,
13915 2,
13916 kNoSSL,
13917 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513918 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113919 {__LINE__,
13920 kProxy,
asankac93076192016-10-03 15:46:0213921 AUTH_NONE,
13922 OK,
13923 kServer,
13924 AUTH_SYNC,
13925 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613926 3,
asankac93076192016-10-03 15:46:0213927 kNoSSL,
13928 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613929 TestRound(kGetProxy, kServerChallenge, OK),
13930 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113931 {__LINE__,
13932 kProxy,
asankac93076192016-10-03 15:46:0213933 AUTH_NONE,
13934 OK,
13935 kServer,
13936 AUTH_ASYNC,
13937 OK,
13938 2,
13939 kNoSSL,
13940 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513941 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113942 {__LINE__,
13943 kProxy,
asankac93076192016-10-03 15:46:0213944 AUTH_NONE,
13945 OK,
13946 kServer,
13947 AUTH_ASYNC,
13948 ERR_INVALID_AUTH_CREDENTIALS,
13949 2,
13950 kNoSSL,
13951 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613952 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213953 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113954 {__LINE__,
13955 kProxy,
asankac93076192016-10-03 15:46:0213956 AUTH_SYNC,
13957 OK,
13958 kServer,
13959 AUTH_NONE,
13960 OK,
13961 2,
13962 kNoSSL,
13963 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513964 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113965 {__LINE__,
13966 kProxy,
asankac93076192016-10-03 15:46:0213967 AUTH_SYNC,
13968 ERR_INVALID_AUTH_CREDENTIALS,
13969 kServer,
13970 AUTH_NONE,
13971 OK,
13972 2,
13973 kNoSSL,
13974 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613975 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113976 {__LINE__,
13977 kProxy,
asankac93076192016-10-03 15:46:0213978 AUTH_ASYNC,
13979 OK,
13980 kServer,
13981 AUTH_NONE,
13982 OK,
13983 2,
13984 kNoSSL,
13985 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513986 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113987 {__LINE__,
13988 kProxy,
asankac93076192016-10-03 15:46:0213989 AUTH_ASYNC,
13990 ERR_INVALID_AUTH_CREDENTIALS,
13991 kServer,
13992 AUTH_NONE,
13993 OK,
13994 2,
13995 kNoSSL,
13996 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613997 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113998 {__LINE__,
13999 kProxy,
14000 AUTH_ASYNC,
14001 ERR_INVALID_AUTH_CREDENTIALS,
14002 kServer,
14003 AUTH_NONE,
14004 OK,
14005 3,
14006 kNoSSL,
14007 {TestRound(kGetProxy, kProxyChallenge, OK),
14008 TestRound(kGetProxy, kProxyChallenge, OK),
14009 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214010 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114011 {__LINE__,
14012 kProxy,
asankac93076192016-10-03 15:46:0214013 AUTH_SYNC,
14014 OK,
14015 kServer,
14016 AUTH_SYNC,
14017 OK,
14018 3,
14019 kNoSSL,
14020 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514021 TestRound(kGetProxyAuth, kServerChallenge, OK),
14022 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114023 {__LINE__,
14024 kProxy,
asankac93076192016-10-03 15:46:0214025 AUTH_SYNC,
14026 OK,
14027 kServer,
14028 AUTH_SYNC,
14029 ERR_INVALID_AUTH_CREDENTIALS,
14030 3,
14031 kNoSSL,
14032 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514033 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614034 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114035 {__LINE__,
14036 kProxy,
asankac93076192016-10-03 15:46:0214037 AUTH_ASYNC,
14038 OK,
14039 kServer,
14040 AUTH_SYNC,
14041 OK,
14042 3,
14043 kNoSSL,
14044 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514045 TestRound(kGetProxyAuth, kServerChallenge, OK),
14046 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114047 {__LINE__,
14048 kProxy,
asankac93076192016-10-03 15:46:0214049 AUTH_ASYNC,
14050 OK,
14051 kServer,
14052 AUTH_SYNC,
14053 ERR_INVALID_AUTH_CREDENTIALS,
14054 3,
14055 kNoSSL,
14056 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514057 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614058 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114059 {__LINE__,
14060 kProxy,
asankac93076192016-10-03 15:46:0214061 AUTH_SYNC,
14062 OK,
14063 kServer,
14064 AUTH_ASYNC,
14065 OK,
14066 3,
14067 kNoSSL,
14068 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514069 TestRound(kGetProxyAuth, kServerChallenge, OK),
14070 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114071 {__LINE__,
14072 kProxy,
14073 AUTH_SYNC,
14074 ERR_INVALID_AUTH_CREDENTIALS,
14075 kServer,
14076 AUTH_ASYNC,
14077 OK,
14078 4,
14079 kNoSSL,
14080 {TestRound(kGetProxy, kProxyChallenge, OK),
14081 TestRound(kGetProxy, kProxyChallenge, OK),
14082 TestRound(kGetProxyAuth, kServerChallenge, OK),
14083 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
14084 {__LINE__,
14085 kProxy,
asankac93076192016-10-03 15:46:0214086 AUTH_SYNC,
14087 OK,
14088 kServer,
14089 AUTH_ASYNC,
14090 ERR_INVALID_AUTH_CREDENTIALS,
14091 3,
14092 kNoSSL,
14093 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514094 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614095 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114096 {__LINE__,
14097 kProxy,
asankac93076192016-10-03 15:46:0214098 AUTH_ASYNC,
14099 OK,
14100 kServer,
14101 AUTH_ASYNC,
14102 OK,
14103 3,
14104 kNoSSL,
14105 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514106 TestRound(kGetProxyAuth, kServerChallenge, OK),
14107 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114108 {__LINE__,
14109 kProxy,
asankac93076192016-10-03 15:46:0214110 AUTH_ASYNC,
14111 OK,
14112 kServer,
14113 AUTH_ASYNC,
14114 ERR_INVALID_AUTH_CREDENTIALS,
14115 3,
14116 kNoSSL,
14117 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514118 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1614119 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114120 {__LINE__,
14121 kProxy,
14122 AUTH_ASYNC,
14123 ERR_INVALID_AUTH_CREDENTIALS,
14124 kServer,
14125 AUTH_ASYNC,
14126 ERR_INVALID_AUTH_CREDENTIALS,
14127 4,
14128 kNoSSL,
14129 {TestRound(kGetProxy, kProxyChallenge, OK),
14130 TestRound(kGetProxy, kProxyChallenge, OK),
14131 TestRound(kGetProxyAuth, kServerChallenge, OK),
14132 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214133 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114134 {__LINE__,
14135 nullptr,
asankac93076192016-10-03 15:46:0214136 AUTH_NONE,
14137 OK,
14138 kSecureServer,
14139 AUTH_NONE,
14140 OK,
14141 1,
14142 0,
14143 {TestRound(kGet, kSuccess, OK)}},
14144 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3114145 {__LINE__,
14146 nullptr,
asankac93076192016-10-03 15:46:0214147 AUTH_NONE,
14148 OK,
14149 kSecureServer,
14150 AUTH_SYNC,
14151 OK,
14152 2,
14153 0,
14154 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514155 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114156 {__LINE__,
14157 nullptr,
asankac93076192016-10-03 15:46:0214158 AUTH_NONE,
14159 OK,
14160 kSecureServer,
14161 AUTH_SYNC,
14162 ERR_INVALID_AUTH_CREDENTIALS,
14163 2,
14164 0,
asankae2257db2016-10-11 22:03:1614165 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114166 {__LINE__,
14167 nullptr,
asankac93076192016-10-03 15:46:0214168 AUTH_NONE,
14169 OK,
14170 kSecureServer,
14171 AUTH_ASYNC,
14172 OK,
14173 2,
14174 0,
14175 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514176 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114177 {__LINE__,
14178 nullptr,
asankac93076192016-10-03 15:46:0214179 AUTH_NONE,
14180 OK,
14181 kSecureServer,
14182 AUTH_ASYNC,
14183 ERR_INVALID_AUTH_CREDENTIALS,
14184 2,
14185 0,
asankae2257db2016-10-11 22:03:1614186 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214187 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114188 {__LINE__,
14189 kProxy,
asankac93076192016-10-03 15:46:0214190 AUTH_NONE,
14191 OK,
14192 kSecureServer,
14193 AUTH_NONE,
14194 OK,
14195 1,
14196 0,
14197 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
14198 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3114199 {__LINE__,
14200 kProxy,
asankac93076192016-10-03 15:46:0214201 AUTH_NONE,
14202 OK,
14203 kSecureServer,
14204 AUTH_SYNC,
14205 OK,
14206 2,
14207 0,
14208 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514209 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114210 {__LINE__,
14211 kProxy,
asankac93076192016-10-03 15:46:0214212 AUTH_NONE,
14213 OK,
14214 kSecureServer,
14215 AUTH_SYNC,
14216 ERR_INVALID_AUTH_CREDENTIALS,
14217 2,
14218 0,
14219 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614220 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114221 {__LINE__,
14222 kProxy,
asankac93076192016-10-03 15:46:0214223 AUTH_NONE,
14224 OK,
14225 kSecureServer,
14226 AUTH_ASYNC,
14227 OK,
14228 2,
14229 0,
14230 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514231 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114232 {__LINE__,
14233 kProxy,
asankac93076192016-10-03 15:46:0214234 AUTH_NONE,
14235 OK,
14236 kSecureServer,
14237 AUTH_ASYNC,
14238 ERR_INVALID_AUTH_CREDENTIALS,
14239 2,
14240 0,
14241 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1614242 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0214243 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114244 {__LINE__,
14245 kProxy,
asankac93076192016-10-03 15:46:0214246 AUTH_SYNC,
14247 OK,
14248 kSecureServer,
14249 AUTH_NONE,
14250 OK,
14251 2,
14252 1,
14253 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514254 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114255 {__LINE__,
14256 kProxy,
asankac93076192016-10-03 15:46:0214257 AUTH_SYNC,
14258 ERR_INVALID_AUTH_CREDENTIALS,
14259 kSecureServer,
14260 AUTH_NONE,
14261 OK,
14262 2,
14263 kNoSSL,
14264 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614265 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114266 {__LINE__,
14267 kProxy,
asankae2257db2016-10-11 22:03:1614268 AUTH_SYNC,
14269 ERR_UNSUPPORTED_AUTH_SCHEME,
14270 kSecureServer,
14271 AUTH_NONE,
14272 OK,
14273 2,
14274 kNoSSL,
14275 {TestRound(kConnect, kProxyChallenge, OK),
14276 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114277 {__LINE__,
14278 kProxy,
asankae2257db2016-10-11 22:03:1614279 AUTH_SYNC,
14280 ERR_UNEXPECTED,
14281 kSecureServer,
14282 AUTH_NONE,
14283 OK,
14284 2,
14285 kNoSSL,
14286 {TestRound(kConnect, kProxyChallenge, OK),
14287 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114288 {__LINE__,
14289 kProxy,
asankac93076192016-10-03 15:46:0214290 AUTH_ASYNC,
14291 OK,
14292 kSecureServer,
14293 AUTH_NONE,
14294 OK,
14295 2,
14296 1,
14297 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514298 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114299 {__LINE__,
14300 kProxy,
asankac93076192016-10-03 15:46:0214301 AUTH_ASYNC,
14302 ERR_INVALID_AUTH_CREDENTIALS,
14303 kSecureServer,
14304 AUTH_NONE,
14305 OK,
14306 2,
14307 kNoSSL,
14308 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614309 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0214310 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114311 {__LINE__,
14312 kProxy,
asankac93076192016-10-03 15:46:0214313 AUTH_SYNC,
14314 OK,
14315 kSecureServer,
14316 AUTH_SYNC,
14317 OK,
14318 3,
14319 1,
14320 {TestRound(kConnect, kProxyChallenge, OK),
14321 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14322 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514323 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114324 {__LINE__,
14325 kProxy,
asankac93076192016-10-03 15:46:0214326 AUTH_SYNC,
14327 OK,
14328 kSecureServer,
14329 AUTH_SYNC,
14330 ERR_INVALID_AUTH_CREDENTIALS,
14331 3,
14332 1,
14333 {TestRound(kConnect, kProxyChallenge, OK),
14334 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14335 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614336 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114337 {__LINE__,
14338 kProxy,
asankac93076192016-10-03 15:46:0214339 AUTH_ASYNC,
14340 OK,
14341 kSecureServer,
14342 AUTH_SYNC,
14343 OK,
14344 3,
14345 1,
14346 {TestRound(kConnect, kProxyChallenge, OK),
14347 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14348 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514349 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114350 {__LINE__,
14351 kProxy,
asankac93076192016-10-03 15:46:0214352 AUTH_ASYNC,
14353 OK,
14354 kSecureServer,
14355 AUTH_SYNC,
14356 ERR_INVALID_AUTH_CREDENTIALS,
14357 3,
14358 1,
14359 {TestRound(kConnect, kProxyChallenge, OK),
14360 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14361 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614362 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114363 {__LINE__,
14364 kProxy,
asankac93076192016-10-03 15:46:0214365 AUTH_SYNC,
14366 OK,
14367 kSecureServer,
14368 AUTH_ASYNC,
14369 OK,
14370 3,
14371 1,
14372 {TestRound(kConnect, kProxyChallenge, OK),
14373 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14374 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514375 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114376 {__LINE__,
14377 kProxy,
asankac93076192016-10-03 15:46:0214378 AUTH_SYNC,
14379 OK,
14380 kSecureServer,
14381 AUTH_ASYNC,
14382 ERR_INVALID_AUTH_CREDENTIALS,
14383 3,
14384 1,
14385 {TestRound(kConnect, kProxyChallenge, OK),
14386 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14387 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614388 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114389 {__LINE__,
14390 kProxy,
asankac93076192016-10-03 15:46:0214391 AUTH_ASYNC,
14392 OK,
14393 kSecureServer,
14394 AUTH_ASYNC,
14395 OK,
14396 3,
14397 1,
14398 {TestRound(kConnect, kProxyChallenge, OK),
14399 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14400 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514401 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114402 {__LINE__,
14403 kProxy,
asankac93076192016-10-03 15:46:0214404 AUTH_ASYNC,
14405 OK,
14406 kSecureServer,
14407 AUTH_ASYNC,
14408 ERR_INVALID_AUTH_CREDENTIALS,
14409 3,
14410 1,
14411 {TestRound(kConnect, kProxyChallenge, OK),
14412 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14413 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614414 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114415 {__LINE__,
14416 kProxy,
14417 AUTH_ASYNC,
14418 ERR_INVALID_AUTH_CREDENTIALS,
14419 kSecureServer,
14420 AUTH_ASYNC,
14421 ERR_INVALID_AUTH_CREDENTIALS,
14422 4,
14423 2,
14424 {TestRound(kConnect, kProxyChallenge, OK),
14425 TestRound(kConnect, kProxyChallenge, OK),
14426 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14427 &kServerChallenge),
14428 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1514429 };
14430
asanka463ca4262016-11-16 02:34:3114431 for (const auto& test_config : test_configs) {
14432 SCOPED_TRACE(::testing::Message() << "Test config at "
14433 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0814434 HttpAuthHandlerMock::Factory* auth_factory(
14435 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714436 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4914437 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2614438
14439 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1514440 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3114441 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0814442 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14443 std::string auth_challenge = "Mock realm=proxy";
14444 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2414445 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14446 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0814447 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2014448 empty_ssl_info, origin,
14449 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814450 auth_handler->SetGenerateExpectation(
14451 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114452 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0814453 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
14454 }
[email protected]044de0642010-06-17 10:42:1514455 }
14456 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0014457 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1514458 std::string auth_challenge = "Mock realm=server";
14459 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2414460 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14461 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1514462 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014463 empty_ssl_info, origin,
14464 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514465 auth_handler->SetGenerateExpectation(
14466 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114467 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0814468 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1614469
14470 // The second handler always succeeds. It should only be used where there
14471 // are multiple auth sessions for server auth in the same network
14472 // transaction using the same auth scheme.
14473 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1914474 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1614475 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
14476 empty_ssl_info, origin,
14477 NetLogWithSource());
14478 second_handler->SetGenerateExpectation(true, OK);
14479 auth_factory->AddMockHandler(second_handler.release(),
14480 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1514481 }
14482 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5914483 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914484 ProxyResolutionService::CreateFixed(test_config.proxy_url,
14485 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514486 } else {
Bence Béky53a5aef2018-03-29 21:54:1214487 session_deps_.proxy_resolution_service =
14488 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1514489 }
14490
14491 HttpRequestInfo request;
14492 request.method = "GET";
14493 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1014494 request.traffic_annotation =
14495 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514496
danakj1fd259a02016-04-16 03:17:0914497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1514498
rchcb68dc62015-05-21 04:45:3614499 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
14500
14501 std::vector<std::vector<MockRead>> mock_reads(1);
14502 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1514503 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214504 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1514505 const TestRound& read_write_round = test_config.rounds[round];
14506
14507 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3614508 mock_reads.back().push_back(read_write_round.read);
14509 mock_writes.back().push_back(read_write_round.write);
14510
14511 // kProxyChallenge uses Proxy-Connection: close which means that the
14512 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5414513 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3614514 mock_reads.push_back(std::vector<MockRead>());
14515 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1514516 }
14517
rchcb68dc62015-05-21 04:45:3614518 if (read_write_round.extra_read) {
14519 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1514520 }
rchcb68dc62015-05-21 04:45:3614521 if (read_write_round.extra_write) {
14522 mock_writes.back().push_back(*read_write_round.extra_write);
14523 }
[email protected]044de0642010-06-17 10:42:1514524
14525 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1514526 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0714527 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1514528 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3614529 }
[email protected]044de0642010-06-17 10:42:1514530
danakj1fd259a02016-04-16 03:17:0914531 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3614532 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1914533 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0114534 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3614535 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3214536 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3614537 }
14538
mmenkecc2298e2015-12-07 18:20:1814539 // Transaction must be created after DataProviders, so it's destroyed before
14540 // they are as well.
14541 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14542
rchcb68dc62015-05-21 04:45:3614543 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214544 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3614545 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1514546 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4114547 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1514548 int rv;
14549 if (round == 0) {
tfarina42834112016-09-22 13:38:2014550 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514551 } else {
[email protected]49639fa2011-12-20 23:22:4114552 rv = trans.RestartWithAuth(
14553 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1514554 }
14555 if (rv == ERR_IO_PENDING)
14556 rv = callback.WaitForResult();
14557
14558 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1614559 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5014560 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5514561 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1514562 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
14563 continue;
14564 }
14565 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5814566 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1514567 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5814568 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1614569 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1514570 }
14571 }
[email protected]e5ae96a2010-04-14 20:12:4514572 }
14573}
14574
bncd16676a2016-07-20 16:23:0114575TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1414576 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1414577 HttpAuthHandlerMock::Factory* auth_factory(
14578 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714579 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1214580 session_deps_.proxy_resolution_service =
14581 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0714582 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1414583
14584 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14585 auth_handler->set_connection_based(true);
14586 std::string auth_challenge = "Mock realm=server";
14587 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2414588 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14589 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4914590 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1414591 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014592 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814593 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1414594
[email protected]c871bce92010-07-15 21:51:1414595 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3514596 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1414597 HttpRequestInfo request;
14598 request.method = "GET";
14599 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1014600 request.traffic_annotation =
14601 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2714602
danakj1fd259a02016-04-16 03:17:0914603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1014604
14605 // Use a TCP Socket Pool with only one connection per group. This is used
14606 // to validate that the TCP socket is not released to the pool between
14607 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4214608 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3614609 CommonConnectJobParams common_connect_job_params(
14610 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2814611 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5914612 50, // Max sockets for pool
14613 1, // Max sockets per group
14614 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3614615 ProxyServer::Direct(), false, // is_for_websockets
David Benjamin151ec6b2019-08-02 19:38:5214616 &common_connect_job_params);
Jeremy Roman0579ed62017-08-29 15:56:1914617 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4014618 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
14619 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4814620 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1014621
bnc691fda62016-08-12 00:43:1614622 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114623 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1414624
14625 const MockWrite kGet(
14626 "GET / HTTP/1.1\r\n"
14627 "Host: www.example.com\r\n"
14628 "Connection: keep-alive\r\n\r\n");
14629 const MockWrite kGetAuth(
14630 "GET / HTTP/1.1\r\n"
14631 "Host: www.example.com\r\n"
14632 "Connection: keep-alive\r\n"
14633 "Authorization: auth_token\r\n\r\n");
14634
14635 const MockRead kServerChallenge(
14636 "HTTP/1.1 401 Unauthorized\r\n"
14637 "WWW-Authenticate: Mock realm=server\r\n"
14638 "Content-Type: text/html; charset=iso-8859-1\r\n"
14639 "Content-Length: 14\r\n\r\n"
14640 "Unauthorized\r\n");
14641 const MockRead kSuccess(
14642 "HTTP/1.1 200 OK\r\n"
14643 "Content-Type: text/html; charset=iso-8859-1\r\n"
14644 "Content-Length: 3\r\n\r\n"
14645 "Yes");
14646
14647 MockWrite writes[] = {
14648 // First round
14649 kGet,
14650 // Second round
14651 kGetAuth,
14652 // Third round
14653 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3014654 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1014655 kGetAuth,
14656 // Competing request
14657 kGet,
[email protected]c871bce92010-07-15 21:51:1414658 };
14659 MockRead reads[] = {
14660 // First round
14661 kServerChallenge,
14662 // Second round
14663 kServerChallenge,
14664 // Third round
[email protected]eca50e122010-09-11 14:03:3014665 kServerChallenge,
14666 // Fourth round
[email protected]c871bce92010-07-15 21:51:1414667 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1014668 // Competing response
14669 kSuccess,
[email protected]c871bce92010-07-15 21:51:1414670 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114671 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0714672 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1414673
Matt Menkef6edce752019-03-19 17:21:5614674 const ClientSocketPool::GroupId kSocketGroup(
14675 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5914676 PrivacyMode::PRIVACY_MODE_DISABLED);
[email protected]7ef4cbbb2011-02-06 11:19:1014677
14678 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1414679 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2014680 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1414681 if (rv == ERR_IO_PENDING)
14682 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114683 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614684 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214685 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814686 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314687 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114688 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14689 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414690
[email protected]7ef4cbbb2011-02-06 11:19:1014691 // In between rounds, another request comes in for the same domain.
14692 // It should not be able to grab the TCP socket that trans has already
14693 // claimed.
bnc691fda62016-08-12 00:43:1614694 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114695 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2014696 rv = trans_compete.Start(&request, callback_compete.callback(),
14697 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114698 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1014699 // callback_compete.WaitForResult at this point would stall forever,
14700 // since the HttpNetworkTransaction does not release the request back to
14701 // the pool until after authentication completes.
14702
14703 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1414704 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614705 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414706 if (rv == ERR_IO_PENDING)
14707 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114708 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614709 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214710 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814711 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314712 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114713 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14714 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414715
[email protected]7ef4cbbb2011-02-06 11:19:1014716 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1414717 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614718 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414719 if (rv == ERR_IO_PENDING)
14720 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114721 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614722 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214723 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814724 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314725 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114726 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14727 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3014728
[email protected]7ef4cbbb2011-02-06 11:19:1014729 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3014730 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614731 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3014732 if (rv == ERR_IO_PENDING)
14733 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114734 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614735 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214736 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814737 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314738 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014739
asanka463ca4262016-11-16 02:34:3114740 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
14741 // auth handler should transition to a DONE state in concert with the remote
14742 // server. But that's not something we can test here with a mock handler.
14743 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
14744 auth_handler->state());
14745
[email protected]7ef4cbbb2011-02-06 11:19:1014746 // Read the body since the fourth round was successful. This will also
14747 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4414748 scoped_refptr<IOBufferWithSize> io_buf =
14749 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1614750 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014751 if (rv == ERR_IO_PENDING)
14752 rv = callback.WaitForResult();
14753 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614754 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014755 EXPECT_EQ(0, rv);
14756 // There are still 0 idle sockets, since the trans_compete transaction
14757 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314758 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014759
14760 // The competing request can now finish. Wait for the headers and then
14761 // read the body.
14762 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0114763 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614764 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014765 if (rv == ERR_IO_PENDING)
14766 rv = callback.WaitForResult();
14767 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614768 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014769 EXPECT_EQ(0, rv);
14770
14771 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314772 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1414773}
14774
[email protected]65041fa2010-05-21 06:56:5314775// This tests the case that a request is issued via http instead of spdy after
14776// npn is negotiated.
bncd16676a2016-07-20 16:23:0114777TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5314778 HttpRequestInfo request;
14779 request.method = "GET";
bncce36dca22015-04-21 22:11:2314780 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014781 request.traffic_annotation =
14782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5314783
14784 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314785 MockWrite(
14786 "GET / HTTP/1.1\r\n"
14787 "Host: www.example.org\r\n"
14788 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5314789 };
14790
14791 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214792 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314793 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214794 MockRead("\r\n"),
14795 MockRead("hello world"),
14796 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5314797 };
14798
[email protected]8ddf8322012-02-23 18:08:0614799 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614800 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5314801
[email protected]bb88e1d32013-05-03 23:11:0714802 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5314803
Ryan Sleevib8d7ea02018-05-07 20:01:0114804 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0714805 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5314806
[email protected]49639fa2011-12-20 23:22:4114807 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5314808
danakj1fd259a02016-04-16 03:17:0914809 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614810 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5314811
tfarina42834112016-09-22 13:38:2014812 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5314813
robpercival214763f2016-07-01 23:27:0114814 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14815 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5314816
bnc691fda62016-08-12 00:43:1614817 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214818 ASSERT_TRUE(response);
14819 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5314820 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14821
14822 std::string response_data;
bnc691fda62016-08-12 00:43:1614823 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5314824 EXPECT_EQ("hello world", response_data);
14825
14826 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214827 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5314828}
[email protected]26ef6582010-06-24 02:30:4714829
bnc55ff9da2015-08-19 18:42:3514830// Simulate the SSL handshake completing with an NPN negotiation followed by an
14831// immediate server closing of the socket.
14832// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0114833TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4714834 HttpRequestInfo request;
14835 request.method = "GET";
bncce36dca22015-04-21 22:11:2314836 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014837 request.traffic_annotation =
14838 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4714839
[email protected]8ddf8322012-02-23 18:08:0614840 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614841 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0714842 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4714843
Ryan Hamilton0239aac2018-05-19 00:03:1314844 spdy::SpdySerializedFrame req(
14845 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114846 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4714847
14848 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614849 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4714850 };
14851
Ryan Sleevib8d7ea02018-05-07 20:01:0114852 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714853 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4714854
[email protected]49639fa2011-12-20 23:22:4114855 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4714856
danakj1fd259a02016-04-16 03:17:0914857 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614858 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4714859
tfarina42834112016-09-22 13:38:2014860 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114861 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14862 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4714863}
[email protected]65d34382010-07-01 18:12:2614864
[email protected]795cbf82013-07-22 09:37:2714865// A subclass of HttpAuthHandlerMock that records the request URL when
14866// it gets it. This is needed since the auth handler may get destroyed
14867// before we get a chance to query it.
14868class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
14869 public:
14870 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
14871
Chris Watkins7a41d3552017-12-01 02:13:2714872 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2714873
14874 protected:
dchengb03027d2014-10-21 12:00:2014875 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
14876 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0914877 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2014878 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2714879 *url_ = request->url;
14880 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0914881 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2714882 }
14883
14884 private:
14885 GURL* url_;
14886};
14887
[email protected]8e6441ca2010-08-19 05:56:3814888// Test that if we cancel the transaction as the connection is completing, that
14889// everything tears down correctly.
bncd16676a2016-07-20 16:23:0114890TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3814891 // Setup everything about the connection to complete synchronously, so that
14892 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
14893 // for is the callback from the HttpStreamRequest.
14894 // Then cancel the transaction.
14895 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3614896 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3814897 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614898 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
14899 MockRead(SYNCHRONOUS, "hello world"),
14900 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3814901 };
14902
[email protected]8e6441ca2010-08-19 05:56:3814903 HttpRequestInfo request;
14904 request.method = "GET";
bncce36dca22015-04-21 22:11:2314905 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014906 request.traffic_annotation =
14907 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3814908
danakj1fd259a02016-04-16 03:17:0914909 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814910 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914911 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2714912
Ryan Sleevib8d7ea02018-05-07 20:01:0114913 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3814914 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714915 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3814916
[email protected]49639fa2011-12-20 23:22:4114917 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3814918
vishal.b62985ca92015-04-17 08:45:5114919 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4114920 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114921 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3814922 trans.reset(); // Cancel the transaction here.
14923
fdoray92e35a72016-06-10 15:54:5514924 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3014925}
14926
[email protected]ecab6e052014-05-16 14:58:1214927// Test that if a transaction is cancelled after receiving the headers, the
14928// stream is drained properly and added back to the socket pool. The main
14929// purpose of this test is to make sure that an HttpStreamParser can be read
14930// from after the HttpNetworkTransaction and the objects it owns have been
14931// deleted.
14932// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0114933TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1214934 MockRead data_reads[] = {
14935 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
14936 MockRead(ASYNC, "Content-Length: 2\r\n"),
14937 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
14938 MockRead(ASYNC, "1"),
14939 // 2 async reads are necessary to trigger a ReadResponseBody call after the
14940 // HttpNetworkTransaction has been deleted.
14941 MockRead(ASYNC, "2"),
14942 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
14943 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114944 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1214945 session_deps_.socket_factory->AddSocketDataProvider(&data);
14946
danakj1fd259a02016-04-16 03:17:0914947 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1214948
14949 {
14950 HttpRequestInfo request;
14951 request.method = "GET";
bncce36dca22015-04-21 22:11:2314952 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014953 request.traffic_annotation =
14954 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1214955
dcheng48459ac22014-08-26 00:46:4114956 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1214957 TestCompletionCallback callback;
14958
tfarina42834112016-09-22 13:38:2014959 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114960 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1214961 callback.WaitForResult();
14962
14963 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214964 ASSERT_TRUE(response);
14965 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1214966 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14967
14968 // The transaction and HttpRequestInfo are deleted.
14969 }
14970
14971 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5514972 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1214973
14974 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4114975 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1214976}
14977
[email protected]76a505b2010-08-25 06:23:0014978// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0114979TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914980 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914981 ProxyResolutionService::CreateFixedFromPacResult(
14982 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114983 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714984 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914985 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014986
[email protected]76a505b2010-08-25 06:23:0014987 HttpRequestInfo request;
14988 request.method = "GET";
bncce36dca22015-04-21 22:11:2314989 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014990 request.traffic_annotation =
14991 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014992
14993 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2314994 MockWrite(
14995 "GET http://www.example.org/ HTTP/1.1\r\n"
14996 "Host: www.example.org\r\n"
14997 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014998 };
14999
15000 MockRead data_reads1[] = {
15001 MockRead("HTTP/1.1 200 OK\r\n"),
15002 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15003 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615004 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015005 };
15006
Ryan Sleevib8d7ea02018-05-07 20:01:0115007 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715008 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0015009
[email protected]49639fa2011-12-20 23:22:4115010 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015011
bnc691fda62016-08-12 00:43:1615012 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915013 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615014 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915015 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15016 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015017
bnc691fda62016-08-12 00:43:1615018 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115019 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015020
15021 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115022 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0015023
bnc691fda62016-08-12 00:43:1615024 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215025 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015026
15027 EXPECT_TRUE(response->headers->IsKeepAlive());
15028 EXPECT_EQ(200, response->headers->response_code());
15029 EXPECT_EQ(100, response->headers->GetContentLength());
15030 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715031 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15032 HostPortPair::FromString("myproxy:70")),
15033 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915034 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15035 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15036 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0015037 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2015038
15039 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615040 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015041 TestLoadTimingNotReusedWithPac(load_timing_info,
15042 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0015043}
15044
15045// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0115046TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5915047 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915048 ProxyResolutionService::CreateFixedFromPacResult(
15049 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115050 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715051 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915052 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015053
[email protected]76a505b2010-08-25 06:23:0015054 HttpRequestInfo request;
15055 request.method = "GET";
bncce36dca22015-04-21 22:11:2315056 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015057 request.traffic_annotation =
15058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015059
15060 // Since we have proxy, should try to establish tunnel.
15061 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715062 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15063 "Host: www.example.org:443\r\n"
15064 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015065
rsleevidb16bb02015-11-12 23:47:1715066 MockWrite("GET / HTTP/1.1\r\n"
15067 "Host: www.example.org\r\n"
15068 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015069 };
15070
15071 MockRead data_reads1[] = {
15072 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15073
15074 MockRead("HTTP/1.1 200 OK\r\n"),
15075 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15076 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615077 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0015078 };
15079
Ryan Sleevib8d7ea02018-05-07 20:01:0115080 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715081 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615082 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715083 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015084
[email protected]49639fa2011-12-20 23:22:4115085 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015086
bnc691fda62016-08-12 00:43:1615087 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0915088 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1615089 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0915090 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
15091 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5015092
bnc691fda62016-08-12 00:43:1615093 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115094 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015095
15096 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115097 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415098 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015099 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015100 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15101 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015102 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015103 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015104 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15105 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015106
bnc691fda62016-08-12 00:43:1615107 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215108 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0015109
15110 EXPECT_TRUE(response->headers->IsKeepAlive());
15111 EXPECT_EQ(200, response->headers->response_code());
15112 EXPECT_EQ(100, response->headers->GetContentLength());
15113 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15114 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715115 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15116 HostPortPair::FromString("myproxy:70")),
15117 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0915118 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
15119 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
15120 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2015121
15122 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615123 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2015124 TestLoadTimingNotReusedWithPac(load_timing_info,
15125 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0015126}
15127
rsleevidb16bb02015-11-12 23:47:1715128// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
15129// literal host.
bncd16676a2016-07-20 16:23:0115130TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5915131 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4915132 ProxyResolutionService::CreateFixedFromPacResult(
15133 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715134 BoundTestNetLog log;
15135 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915136 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1715137
15138 HttpRequestInfo request;
15139 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1515140 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1015141 request.traffic_annotation =
15142 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1715143
15144 // Since we have proxy, should try to establish tunnel.
15145 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1515146 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
15147 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1715148 "Proxy-Connection: keep-alive\r\n\r\n"),
15149
15150 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1515151 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1715152 "Connection: keep-alive\r\n\r\n"),
15153 };
15154
15155 MockRead data_reads1[] = {
15156 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15157
15158 MockRead("HTTP/1.1 200 OK\r\n"),
15159 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15160 MockRead("Content-Length: 100\r\n\r\n"),
15161 MockRead(SYNCHRONOUS, OK),
15162 };
15163
Ryan Sleevib8d7ea02018-05-07 20:01:0115164 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1715165 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15166 SSLSocketDataProvider ssl(ASYNC, OK);
15167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15168
15169 TestCompletionCallback callback1;
15170
bnc691fda62016-08-12 00:43:1615171 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1715172
bnc691fda62016-08-12 00:43:1615173 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115174 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1715175
15176 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115177 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5415178 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1715179 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015180 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15181 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715182 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015183 entries, pos,
15184 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15185 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1715186
bnc691fda62016-08-12 00:43:1615187 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5215188 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1715189
15190 EXPECT_TRUE(response->headers->IsKeepAlive());
15191 EXPECT_EQ(200, response->headers->response_code());
15192 EXPECT_EQ(100, response->headers->GetContentLength());
15193 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
15194 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4715195 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
15196 HostPortPair::FromString("myproxy:70")),
15197 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1715198
15199 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1615200 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1715201 TestLoadTimingNotReusedWithPac(load_timing_info,
15202 CONNECT_TIMING_HAS_SSL_TIMES);
15203}
15204
[email protected]76a505b2010-08-25 06:23:0015205// Test a basic HTTPS GET request through a proxy, but the server hangs up
15206// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0115207TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4915208 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15209 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115210 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715211 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0915212 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0015213
[email protected]76a505b2010-08-25 06:23:0015214 HttpRequestInfo request;
15215 request.method = "GET";
bncce36dca22015-04-21 22:11:2315216 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015217 request.traffic_annotation =
15218 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0015219
15220 // Since we have proxy, should try to establish tunnel.
15221 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1715222 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15223 "Host: www.example.org:443\r\n"
15224 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015225
rsleevidb16bb02015-11-12 23:47:1715226 MockWrite("GET / HTTP/1.1\r\n"
15227 "Host: www.example.org\r\n"
15228 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0015229 };
15230
15231 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0015232 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0615233 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0015234 };
15235
Ryan Sleevib8d7ea02018-05-07 20:01:0115236 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0715237 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0615238 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0715239 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0015240
[email protected]49639fa2011-12-20 23:22:4115241 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0015242
bnc691fda62016-08-12 00:43:1615243 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5015244
bnc691fda62016-08-12 00:43:1615245 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0115246 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0015247
15248 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0115249 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5415250 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0015251 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0015252 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15253 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015254 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015255 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015256 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15257 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015258}
15259
[email protected]749eefa82010-09-13 22:14:0315260// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0115261TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1315262 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4915263 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115264 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0315265
Raul Tambre94493c652019-03-11 17:18:3515266 spdy::SpdySerializedFrame resp(
15267 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315268 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0315269 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115270 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315271 };
15272
Ryan Sleevib8d7ea02018-05-07 20:01:0115273 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715274 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315275
[email protected]8ddf8322012-02-23 18:08:0615276 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615277 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715278 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315279
danakj1fd259a02016-04-16 03:17:0915280 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315281
15282 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315283 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015284 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115285 PRIVACY_MODE_DISABLED,
15286 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2715287 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215288 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315289
15290 HttpRequestInfo request;
15291 request.method = "GET";
bncce36dca22015-04-21 22:11:2315292 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015293 request.traffic_annotation =
15294 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0315295
bnc691fda62016-08-12 00:43:1615296 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0315297
[email protected]41d64e82013-07-03 22:44:2615298 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015299 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115300 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15301 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0315302}
15303
[email protected]73b8dd222010-11-11 19:55:2415304// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1615305// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0215306void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0715307 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2915308 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715309 request_info.url = GURL("https://www.example.com/");
15310 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915311 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015312 request_info.traffic_annotation =
15313 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715314
[email protected]8ddf8322012-02-23 18:08:0615315 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2915316 MockWrite data_writes[] = {
15317 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2415318 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115319 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715320 session_deps_.socket_factory->AddSocketDataProvider(&data);
15321 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2415322
danakj1fd259a02016-04-16 03:17:0915323 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615324 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2415325
[email protected]49639fa2011-12-20 23:22:4115326 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015327 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2915328 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2415329 rv = callback.WaitForResult();
15330 ASSERT_EQ(error, rv);
15331}
15332
bncd16676a2016-07-20 16:23:0115333TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2415334 // Just check a grab bag of cert errors.
15335 static const int kErrors[] = {
15336 ERR_CERT_COMMON_NAME_INVALID,
15337 ERR_CERT_AUTHORITY_INVALID,
15338 ERR_CERT_DATE_INVALID,
15339 };
Avi Drissman4365a4782018-12-28 19:26:2415340 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0615341 CheckErrorIsPassedBack(kErrors[i], ASYNC);
15342 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2415343 }
15344}
15345
[email protected]bd0b6772011-01-11 19:59:3015346// Ensure that a client certificate is removed from the SSL client auth
15347// cache when:
15348// 1) No proxy is involved.
15349// 2) TLS False Start is disabled.
15350// 3) The initial TLS handshake requests a client certificate.
15351// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115352TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915353 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715354 request_info.url = GURL("https://www.example.com/");
15355 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915356 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015357 request_info.traffic_annotation =
15358 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715359
David Benjamin1c4b6d012019-07-08 17:12:5715360 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115361 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015362
15363 // [ssl_]data1 contains the data for the first SSL handshake. When a
15364 // CertificateRequest is received for the first time, the handshake will
15365 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2915366 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015367 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715368 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115369 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715370 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015371
15372 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
15373 // False Start is not being used, the result of the SSL handshake will be
15374 // returned as part of the SSLClientSocket::Connect() call. This test
15375 // matches the result of a server sending a handshake_failure alert,
15376 // rather than a Finished message, because it requires a client
15377 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2915378 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3015379 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0115381 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0715382 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015383
15384 // [ssl_]data3 contains the data for the third SSL handshake. When a
15385 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1315386 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
15387 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3015388 // of the HttpNetworkTransaction. Because this test failure is due to
15389 // requiring a client certificate, this fallback handshake should also
15390 // fail.
ttuttle859dc7a2015-04-23 19:42:2915391 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1315392 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3015393 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115395 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0715396 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015397
[email protected]80c75f682012-05-26 16:22:1715398 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
15399 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4215400 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
15401 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1715402 // of the HttpNetworkTransaction. Because this test failure is due to
15403 // requiring a client certificate, this fallback handshake should also
15404 // fail.
ttuttle859dc7a2015-04-23 19:42:2915405 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1715406 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715407 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115408 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0715409 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715410
danakj1fd259a02016-04-16 03:17:0915411 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615412 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015413
[email protected]bd0b6772011-01-11 19:59:3015414 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4115415 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015416 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115417 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015418
15419 // Complete the SSL handshake, which should abort due to requiring a
15420 // client certificate.
15421 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115422 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015423
15424 // Indicate that no certificate should be supplied. From the perspective
15425 // of SSLClientCertCache, NULL is just as meaningful as a real
15426 // certificate, so this is the same as supply a
15427 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515428 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115429 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015430
15431 // Ensure the certificate was added to the client auth cache before
15432 // allowing the connection to continue restarting.
15433 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415434 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115435 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415436 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215437 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015438
15439 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715440 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15441 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015442 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115443 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015444
15445 // Ensure that the client certificate is removed from the cache on a
15446 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115447 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415448 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015449}
15450
15451// Ensure that a client certificate is removed from the SSL client auth
15452// cache when:
15453// 1) No proxy is involved.
15454// 2) TLS False Start is enabled.
15455// 3) The initial TLS handshake requests a client certificate.
15456// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115457TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915458 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715459 request_info.url = GURL("https://www.example.com/");
15460 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915461 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015462 request_info.traffic_annotation =
15463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715464
David Benjamin1c4b6d012019-07-08 17:12:5715465 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115466 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015467
15468 // When TLS False Start is used, SSLClientSocket::Connect() calls will
15469 // return successfully after reading up to the peer's Certificate message.
15470 // This is to allow the caller to call SSLClientSocket::Write(), which can
15471 // enqueue application data to be sent in the same packet as the
15472 // ChangeCipherSpec and Finished messages.
15473 // The actual handshake will be finished when SSLClientSocket::Read() is
15474 // called, which expects to process the peer's ChangeCipherSpec and
15475 // Finished messages. If there was an error negotiating with the peer,
15476 // such as due to the peer requiring a client certificate when none was
15477 // supplied, the alert sent by the peer won't be processed until Read() is
15478 // called.
15479
15480 // Like the non-False Start case, when a client certificate is requested by
15481 // the peer, the handshake is aborted during the Connect() call.
15482 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2915483 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015484 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715485 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115486 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715487 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015488
15489 // When a client certificate is supplied, Connect() will not be aborted
15490 // when the peer requests the certificate. Instead, the handshake will
15491 // artificially succeed, allowing the caller to write the HTTP request to
15492 // the socket. The handshake messages are not processed until Read() is
15493 // called, which then detects that the handshake was aborted, due to the
15494 // peer sending a handshake_failure because it requires a client
15495 // certificate.
ttuttle859dc7a2015-04-23 19:42:2915496 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015497 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715498 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2915499 MockRead data2_reads[] = {
15500 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3015501 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115502 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715503 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015504
15505 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1715506 // the data for the SSL handshake once the TLSv1.1 connection falls back to
15507 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915508 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015509 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715510 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115511 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715512 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015513
[email protected]80c75f682012-05-26 16:22:1715514 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
15515 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915516 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1715517 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715518 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115519 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715520 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715521
[email protected]7799de12013-05-30 05:52:5115522 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2915523 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5115524 ssl_data5.cert_request_info = cert_request.get();
15525 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0115526 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5115527 session_deps_.socket_factory->AddSocketDataProvider(&data5);
15528
danakj1fd259a02016-04-16 03:17:0915529 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615530 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015531
[email protected]bd0b6772011-01-11 19:59:3015532 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4115533 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015534 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115535 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015536
15537 // Complete the SSL handshake, which should abort due to requiring a
15538 // client certificate.
15539 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115540 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015541
15542 // Indicate that no certificate should be supplied. From the perspective
15543 // of SSLClientCertCache, NULL is just as meaningful as a real
15544 // certificate, so this is the same as supply a
15545 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515546 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115547 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015548
15549 // Ensure the certificate was added to the client auth cache before
15550 // allowing the connection to continue restarting.
15551 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415552 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115553 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415554 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215555 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015556
[email protected]bd0b6772011-01-11 19:59:3015557 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715558 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15559 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015560 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115561 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015562
15563 // Ensure that the client certificate is removed from the cache on a
15564 // handshake failure.
David Benjaminbac8dff2019-08-07 01:30:4115565 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
svaldez7872fd02015-11-19 21:10:5415566 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015567}
15568
[email protected]8c405132011-01-11 22:03:1815569// Ensure that a client certificate is removed from the SSL client auth
15570// cache when:
15571// 1) An HTTPS proxy is involved.
15572// 3) The HTTPS proxy requests a client certificate.
15573// 4) The client supplies an invalid/unacceptable certificate for the
15574// proxy.
bncd16676a2016-07-20 16:23:0115575TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4915576 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15577 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115578 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715579 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1815580
David Benjamin3b94b0f2019-04-25 23:07:5215581 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115582 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1815583
David Benjamin3b94b0f2019-04-25 23:07:5215584 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
15585 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2915586 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1815587 requests[0].url = GURL("https://www.example.com/");
15588 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915589 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015590 requests[0].traffic_annotation =
15591 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815592
David Benjamin3b94b0f2019-04-25 23:07:5215593 // HTTPS requests are tunneled.
15594 MockWrite https_writes[] = {
15595 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
15596 "Host: www.example.com:443\r\n"
15597 "Proxy-Connection: keep-alive\r\n\r\n"),
15598 };
15599
[email protected]8c405132011-01-11 22:03:1815600 requests[1].url = GURL("http://www.example.com/");
15601 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915602 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015603 requests[1].traffic_annotation =
15604 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815605
David Benjamin3b94b0f2019-04-25 23:07:5215606 // HTTP requests are not.
15607 MockWrite http_writes[] = {
15608 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
15609 "Host: www.example.com\r\n"
15610 "Proxy-Connection: keep-alive\r\n\r\n"),
15611 };
[email protected]8c405132011-01-11 22:03:1815612
David Benjamin3b94b0f2019-04-25 23:07:5215613 // When the server rejects the client certificate, it will close the
15614 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
15615 // TLS 1.2 with False Start), the error is returned out of the first Read().
15616 for (bool reject_in_connect : {true, false}) {
15617 SCOPED_TRACE(reject_in_connect);
15618 // Client certificate errors are typically signaled with
15619 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
15620 // protocol error.
15621 for (Error reject_error :
15622 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
15623 SCOPED_TRACE(reject_error);
15624 // Tunneled and non-tunneled requests are handled differently. Test both.
15625 for (const HttpRequestInfo& request : requests) {
15626 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1815627
David Benjamin3b94b0f2019-04-25 23:07:5215628 session_deps_.socket_factory =
15629 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1815630
David Benjamin3b94b0f2019-04-25 23:07:5215631 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
15632 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
15633 // for proxies. Rather than represending the endpoint
15634 // (www.example.com:443), they represent failures with the HTTPS proxy
15635 // (proxy:70).
15636 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
15637 ssl_data1.cert_request_info = cert_request.get();
15638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15639 StaticSocketDataProvider data1;
15640 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1815641
David Benjamin3b94b0f2019-04-25 23:07:5215642 base::Optional<SSLSocketDataProvider> ssl_data2;
15643 base::Optional<StaticSocketDataProvider> data2;
15644 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
15645 if (reject_in_connect) {
15646 ssl_data2.emplace(ASYNC, reject_error);
15647 // There are no reads or writes.
15648 data2.emplace();
15649 } else {
15650 ssl_data2.emplace(ASYNC, OK);
15651 // We will get one Write() in before observing the error in Read().
15652 if (request.url.SchemeIsCryptographic()) {
15653 data2.emplace(error_in_read, https_writes);
15654 } else {
15655 data2.emplace(error_in_read, http_writes);
15656 }
15657 }
15658 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1815659
David Benjamin3b94b0f2019-04-25 23:07:5215660 session_deps_.socket_factory->AddSSLSocketDataProvider(
15661 &ssl_data2.value());
15662 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1815663
David Benjamin3b94b0f2019-04-25 23:07:5215664 std::unique_ptr<HttpNetworkSession> session =
15665 CreateSession(&session_deps_);
15666 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15667
15668 // Begin the SSL handshake with the proxy.
15669 TestCompletionCallback callback;
15670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15671 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15672
15673 // Complete the SSL handshake, which should abort due to requiring a
15674 // client certificate.
15675 rv = callback.WaitForResult();
15676 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15677
15678 // Indicate that no certificate should be supplied. From the
15679 // perspective of SSLClientCertCache, NULL is just as meaningful as a
15680 // real certificate, so this is the same as supply a
15681 // legitimate-but-unacceptable certificate.
15682 rv =
15683 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
15684 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15685
15686 // Ensure the certificate was added to the client auth cache before
15687 // allowing the connection to continue restarting.
15688 scoped_refptr<X509Certificate> client_cert;
15689 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115690 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215691 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15692 ASSERT_FALSE(client_cert);
15693 // Ensure the certificate was NOT cached for the endpoint. This only
15694 // applies to HTTPS requests, but is fine to check for HTTP requests.
David Benjaminbac8dff2019-08-07 01:30:4115695 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215696 HostPortPair("www.example.com", 443), &client_cert,
15697 &client_private_key));
15698
15699 // Restart the handshake. This will consume ssl_data2. The result code
15700 // is checked against what ssl_data2 should return.
15701 rv = callback.WaitForResult();
15702 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
15703 IsError(reject_error)));
15704
15705 // Now that the new handshake has failed, ensure that the client
15706 // certificate was removed from the client auth cache.
David Benjaminbac8dff2019-08-07 01:30:4115707 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215708 HostPortPair("proxy", 70), &client_cert, &client_private_key));
David Benjaminbac8dff2019-08-07 01:30:4115709 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
David Benjamin3b94b0f2019-04-25 23:07:5215710 HostPortPair("www.example.com", 443), &client_cert,
15711 &client_private_key));
15712 }
15713 }
[email protected]8c405132011-01-11 22:03:1815714 }
15715}
15716
David Benjamin1a0566082019-04-30 07:36:1915717// Test that HttpNetworkTransaction correctly handles (mocked) certificate
15718// requests during a TLS renegotiation.
15719TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
15720 HttpRequestInfo request_info;
15721 request_info.url = GURL("https://www.example.com/");
15722 request_info.method = "GET";
15723 request_info.load_flags = LOAD_NORMAL;
15724 request_info.traffic_annotation =
15725 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15726
15727 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
15728 cert_request->host_and_port = HostPortPair("www.example.com", 443);
15729
15730 std::unique_ptr<FakeClientCertIdentity> identity =
15731 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
15732 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
15733 ASSERT_TRUE(identity);
15734
15735 // The first connection's handshake succeeds, but we get
15736 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
15737 SSLSocketDataProvider ssl_data1(ASYNC, OK);
15738 ssl_data1.cert_request_info = cert_request.get();
15739 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15740 MockWrite data1_writes[] = {
15741 MockWrite("GET / HTTP/1.1\r\n"
15742 "Host: www.example.com\r\n"
15743 "Connection: keep-alive\r\n\r\n"),
15744 };
15745 MockRead data1_reads[] = {
15746 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
15747 };
15748 StaticSocketDataProvider data1(data1_reads, data1_writes);
15749 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15750
15751 // After supplying with certificate, we restart the request from the top,
15752 // which succeeds this time.
15753 SSLSocketDataProvider ssl_data2(ASYNC, OK);
15754 ssl_data2.expected_send_client_cert = true;
15755 ssl_data2.expected_client_cert = identity->certificate();
15756 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
15757 MockWrite data2_writes[] = {
15758 MockWrite("GET / HTTP/1.1\r\n"
15759 "Host: www.example.com\r\n"
15760 "Connection: keep-alive\r\n\r\n"),
15761 };
15762 MockRead data2_reads[] = {
15763 MockRead("HTTP/1.1 200 OK\r\n"
15764 "Content-Length: 0\r\n\r\n"),
15765 };
15766 StaticSocketDataProvider data2(data2_reads, data2_writes);
15767 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15768
15769 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
15770 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15771
15772 TestCompletionCallback callback;
15773 int rv = callback.GetResult(
15774 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
15775 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15776
15777 rv = trans.RestartWithCertificate(identity->certificate(),
15778 identity->ssl_private_key(),
15779 callback.callback());
15780 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15781
15782 // Ensure the certificate was added to the client auth cache
15783 // allowing the connection to continue restarting.
15784 scoped_refptr<X509Certificate> client_cert;
15785 scoped_refptr<SSLPrivateKey> client_private_key;
David Benjaminbac8dff2019-08-07 01:30:4115786 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915787 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15788 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15789
15790 // Complete the handshake. The request now succeeds.
15791 rv = callback.WaitForResult();
15792 ASSERT_THAT(rv, IsError(OK));
15793 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
15794
15795 // The client certificate remains in the cache.
David Benjaminbac8dff2019-08-07 01:30:4115796 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
David Benjamin1a0566082019-04-30 07:36:1915797 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15798 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15799}
15800
bncd16676a2016-07-20 16:23:0115801TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4615802 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915803 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915804 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615805
bnc032658ba2016-09-26 18:17:1515806 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615807
Ryan Hamilton0239aac2018-05-19 00:03:1315808 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915809 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815810 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315811 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715812 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615813 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115814 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615815 };
Ryan Hamilton0239aac2018-05-19 00:03:1315816 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515817 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315818 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115819 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315820 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515821 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315822 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115823 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615824 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115825 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15826 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315827 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615828 };
15829
eroman36d84e54432016-03-17 03:23:0215830 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215831 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115832 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715833 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615834
[email protected]aa22b242011-11-16 18:58:2915835 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615836 HttpRequestInfo request1;
15837 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315838 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615839 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015840 request1.traffic_annotation =
15841 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015842 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615843
tfarina42834112016-09-22 13:38:2015844 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115845 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15846 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615847
15848 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215849 ASSERT_TRUE(response);
15850 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215851 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615852
15853 std::string response_data;
robpercival214763f2016-07-01 23:27:0115854 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615855 EXPECT_EQ("hello!", response_data);
15856
bnca4d611d2016-09-22 19:55:3715857 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315858 rv = session_deps_.host_resolver->LoadIntoCache(
15859 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0115860 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4615861
15862 HttpRequestInfo request2;
15863 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715864 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4615865 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015866 request2.traffic_annotation =
15867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015868 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615869
tfarina42834112016-09-22 13:38:2015870 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115871 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15872 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615873
15874 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215875 ASSERT_TRUE(response);
15876 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215877 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615878 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215879 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115880 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615881 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4615882}
15883
bncd16676a2016-07-20 16:23:0115884TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0215885 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915886 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915887 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0215888
bnc032658ba2016-09-26 18:17:1515889 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0215890
Ryan Hamilton0239aac2018-05-19 00:03:1315891 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915892 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815893 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315894 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715895 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0215896 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115897 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0215898 };
Ryan Hamilton0239aac2018-05-19 00:03:1315899 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515900 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315901 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115902 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315903 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515904 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315905 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115906 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0215907 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115908 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15909 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315910 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0215911 };
15912
eroman36d84e54432016-03-17 03:23:0215913 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215914 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115915 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715916 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0215917
15918 TestCompletionCallback callback;
15919 HttpRequestInfo request1;
15920 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315921 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0215922 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015923 request1.traffic_annotation =
15924 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015925 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215926
tfarina42834112016-09-22 13:38:2015927 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115928 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15929 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215930
15931 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215932 ASSERT_TRUE(response);
15933 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215934 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215935
15936 std::string response_data;
robpercival214763f2016-07-01 23:27:0115937 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215938 EXPECT_EQ("hello!", response_data);
15939
15940 HttpRequestInfo request2;
15941 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715942 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0215943 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015944 request2.traffic_annotation =
15945 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015946 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215947
tfarina42834112016-09-22 13:38:2015948 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115949 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15950 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215951
15952 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215953 ASSERT_TRUE(response);
15954 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215955 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215956 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215957 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115958 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215959 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0215960}
15961
bnc8016c1f2017-03-31 02:11:2915962// Regression test for https://crbug.com/546991.
15963// The server might not be able to serve an IP pooled request, and might send a
15964// 421 Misdirected Request response status to indicate this.
15965// HttpNetworkTransaction should reset the request and retry without IP pooling.
15966TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
15967 // Two hosts resolve to the same IP address.
15968 const std::string ip_addr = "1.2.3.4";
15969 IPAddress ip;
15970 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15971 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15972
Jeremy Roman0579ed62017-08-29 15:56:1915973 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2915974 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15975 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15976
15977 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15978
15979 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315980 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2915981 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15982 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315983 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2915984 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315985 spdy::SpdySerializedFrame rst(
15986 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2915987 MockWrite writes1[] = {
15988 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15989 CreateMockWrite(rst, 6),
15990 };
15991
15992 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315993 spdy::SpdySerializedFrame resp1(
15994 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15995 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15996 spdy::SpdyHeaderBlock response_headers;
15997 response_headers[spdy::kHttp2StatusHeader] = "421";
15998 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2915999 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
16000 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16001 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16002
16003 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116004 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2916005 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16006
16007 AddSSLSocketData();
16008
16009 // Retry the second request on a second connection.
16010 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316011 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2916012 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16013 MockWrite writes2[] = {
16014 CreateMockWrite(req3, 0),
16015 };
16016
Ryan Hamilton0239aac2018-05-19 00:03:1316017 spdy::SpdySerializedFrame resp3(
16018 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
16019 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2916020 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16021 MockRead(ASYNC, 0, 3)};
16022
16023 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116024 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2916025 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16026
16027 AddSSLSocketData();
16028
16029 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316030 int rv = session_deps_.host_resolver->LoadIntoCache(
16031 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2916032 EXPECT_THAT(rv, IsOk());
16033
16034 HttpRequestInfo request1;
16035 request1.method = "GET";
16036 request1.url = GURL("https://www.example.org/");
16037 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016038 request1.traffic_annotation =
16039 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916040 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16041
Eric Orthf4db66a2019-02-19 21:35:3316042 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2916043 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16044 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16045 rv = callback.WaitForResult();
16046 EXPECT_THAT(rv, IsOk());
16047
16048 const HttpResponseInfo* response = trans1.GetResponseInfo();
16049 ASSERT_TRUE(response);
16050 ASSERT_TRUE(response->headers);
16051 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16052 EXPECT_TRUE(response->was_fetched_via_spdy);
16053 EXPECT_TRUE(response->was_alpn_negotiated);
16054 std::string response_data;
16055 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16056 EXPECT_EQ("hello!", response_data);
16057
16058 HttpRequestInfo request2;
16059 request2.method = "GET";
16060 request2.url = GURL("https://mail.example.org/");
16061 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016062 request2.traffic_annotation =
16063 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2916064 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16065
16066 BoundTestNetLog log;
16067 rv = trans2.Start(&request2, callback.callback(), log.bound());
16068 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16069 rv = callback.WaitForResult();
16070 EXPECT_THAT(rv, IsOk());
16071
16072 response = trans2.GetResponseInfo();
16073 ASSERT_TRUE(response);
16074 ASSERT_TRUE(response->headers);
16075 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16076 EXPECT_TRUE(response->was_fetched_via_spdy);
16077 EXPECT_TRUE(response->was_alpn_negotiated);
16078 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16079 EXPECT_EQ("hello!", response_data);
16080
Eric Roman79cc7552019-07-19 02:17:5416081 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5916082 ExpectLogContainsSomewhere(
16083 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2916084 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5916085}
16086
16087// Test that HTTP 421 responses are properly returned to the caller if received
16088// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
16089// portions of the response.
16090TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
16091 // Two hosts resolve to the same IP address.
16092 const std::string ip_addr = "1.2.3.4";
16093 IPAddress ip;
16094 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
16095 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16096
Jeremy Roman0579ed62017-08-29 15:56:1916097 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5916098 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
16099 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
16100
16101 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16102
16103 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1316104 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5916105 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
16106 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316107 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5916108 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316109 spdy::SpdySerializedFrame rst(
16110 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5916111 MockWrite writes1[] = {
16112 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
16113 CreateMockWrite(rst, 6),
16114 };
16115
16116 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1316117 spdy::SpdySerializedFrame resp1(
16118 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
16119 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
16120 spdy::SpdyHeaderBlock response_headers;
16121 response_headers[spdy::kHttp2StatusHeader] = "421";
16122 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5916123 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
16124 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
16125 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
16126
16127 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116128 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5916129 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16130
16131 AddSSLSocketData();
16132
16133 // Retry the second request on a second connection. It returns 421 Misdirected
16134 // Retry again.
16135 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1316136 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5916137 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
16138 MockWrite writes2[] = {
16139 CreateMockWrite(req3, 0),
16140 };
16141
Ryan Hamilton0239aac2018-05-19 00:03:1316142 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5916143 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1316144 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5916145 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
16146 MockRead(ASYNC, 0, 3)};
16147
16148 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116149 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5916150 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16151
16152 AddSSLSocketData();
16153
16154 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316155 int rv = session_deps_.host_resolver->LoadIntoCache(
16156 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5916157 EXPECT_THAT(rv, IsOk());
16158
16159 HttpRequestInfo request1;
16160 request1.method = "GET";
16161 request1.url = GURL("https://www.example.org/");
16162 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016163 request1.traffic_annotation =
16164 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916165 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16166
Eric Orthf4db66a2019-02-19 21:35:3316167 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5916168 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
16169 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16170 rv = callback.WaitForResult();
16171 EXPECT_THAT(rv, IsOk());
16172
16173 const HttpResponseInfo* response = trans1.GetResponseInfo();
16174 ASSERT_TRUE(response);
16175 ASSERT_TRUE(response->headers);
16176 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
16177 EXPECT_TRUE(response->was_fetched_via_spdy);
16178 EXPECT_TRUE(response->was_alpn_negotiated);
16179 std::string response_data;
16180 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
16181 EXPECT_EQ("hello!", response_data);
16182
16183 HttpRequestInfo request2;
16184 request2.method = "GET";
16185 request2.url = GURL("https://mail.example.org/");
16186 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016187 request2.traffic_annotation =
16188 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5916189 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16190
16191 BoundTestNetLog log;
16192 rv = trans2.Start(&request2, callback.callback(), log.bound());
16193 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16194 rv = callback.WaitForResult();
16195 EXPECT_THAT(rv, IsOk());
16196
16197 // After a retry, the 421 Misdirected Request is reported back up to the
16198 // caller.
16199 response = trans2.GetResponseInfo();
16200 ASSERT_TRUE(response);
16201 ASSERT_TRUE(response->headers);
16202 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
16203 EXPECT_TRUE(response->was_fetched_via_spdy);
16204 EXPECT_TRUE(response->was_alpn_negotiated);
16205 EXPECT_TRUE(response->ssl_info.cert);
16206 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
16207 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2916208}
16209
bncd16676a2016-07-20 16:23:0116210TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1316211 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3416212 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
16213 session_deps_.host_resolver =
16214 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0916215 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4616216
bnc032658ba2016-09-26 18:17:1516217 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4616218
Ryan Hamilton0239aac2018-05-19 00:03:1316219 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916220 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3816221 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1316222 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3716223 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4616224 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116225 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4616226 };
Ryan Hamilton0239aac2018-05-19 00:03:1316227 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516228 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316229 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116230 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1316231 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516232 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316233 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116234 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4616235 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116236 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
16237 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1316238 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4616239 };
16240
eroman36d84e54432016-03-17 03:23:0216241 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0216242 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0116243 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0716244 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4616245
[email protected]aa22b242011-11-16 18:58:2916246 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4616247 HttpRequestInfo request1;
16248 request1.method = "GET";
bncce36dca22015-04-21 22:11:2316249 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4616250 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016251 request1.traffic_annotation =
16252 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016253 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616254
tfarina42834112016-09-22 13:38:2016255 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116256 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16257 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616258
16259 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216260 ASSERT_TRUE(response);
16261 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216262 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616263
16264 std::string response_data;
robpercival214763f2016-07-01 23:27:0116265 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616266 EXPECT_EQ("hello!", response_data);
16267
16268 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316269 rv = session_deps_.host_resolver->LoadIntoCache(
16270 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116271 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616272
16273 HttpRequestInfo request2;
16274 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716275 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616276 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016277 request2.traffic_annotation =
16278 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016279 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616280
tfarina42834112016-09-22 13:38:2016281 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116282 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16283 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616284
16285 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216286 ASSERT_TRUE(response);
16287 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216288 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616289 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216290 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116291 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616292 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616293}
16294
bncd16676a2016-07-20 16:23:0116295TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2316296 const std::string https_url = "https://www.example.org:8080/";
16297 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416298
16299 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1316300 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916301 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0416302
16303 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116304 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0416305 };
16306
Raul Tambre94493c652019-03-11 17:18:3516307 spdy::SpdySerializedFrame resp1(
16308 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316309 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116310 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5916311 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0416312
Ryan Sleevib8d7ea02018-05-07 20:01:0116313 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416314 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716315 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416316
16317 // HTTP GET for the HTTP URL
16318 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1316319 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3416320 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2316321 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3416322 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0416323 };
16324
16325 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1316326 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
16327 MockRead(ASYNC, 2, "hello"),
16328 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0416329 };
16330
Ryan Sleevib8d7ea02018-05-07 20:01:0116331 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0416332
[email protected]8450d722012-07-02 19:14:0416333 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616334 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16336 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16337 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0416338
danakj1fd259a02016-04-16 03:17:0916339 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0416340
16341 // Start the first transaction to set up the SpdySession
16342 HttpRequestInfo request1;
16343 request1.method = "GET";
16344 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416345 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016346 request1.traffic_annotation =
16347 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016348 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416349 TestCompletionCallback callback1;
16350 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016351 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516352 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416353
robpercival214763f2016-07-01 23:27:0116354 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416355 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16356
16357 // Now, start the HTTP request
16358 HttpRequestInfo request2;
16359 request2.method = "GET";
16360 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416361 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016362 request2.traffic_annotation =
16363 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016364 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416365 TestCompletionCallback callback2;
16366 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016367 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516368 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416369
robpercival214763f2016-07-01 23:27:0116370 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416371 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16372}
16373
bnc5452e2a2015-05-08 16:27:4216374// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
16375// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0116376TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2516377 url::SchemeHostPort server("https", "www.example.org", 443);
16378 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4216379
bnc8bef8da22016-05-30 01:28:2516380 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4216381 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616382 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216383 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16384
16385 // No data should be read from the alternative, because HTTP/1.1 is
16386 // negotiated.
16387 StaticSocketDataProvider data;
16388 session_deps_.socket_factory->AddSocketDataProvider(&data);
16389
16390 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4616391 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4216392 // mocked. This way the request relies on the alternate Job.
16393 StaticSocketDataProvider data_refused;
16394 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16395 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16396
zhongyi3d4a55e72016-04-22 20:36:4616397 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916398 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016399 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216400 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116401 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216402 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116403 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716404 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216405
bnc5452e2a2015-05-08 16:27:4216406 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4616407 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216408 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2516409 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1016410 request.traffic_annotation =
16411 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216412 TestCompletionCallback callback;
16413
16414 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5216415 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2016416 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5216417 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4216418}
16419
bnc40448a532015-05-11 19:13:1416420// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4616421// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1416422// succeeds, the request should succeed, even if the latter fails because
16423// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0116424TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2516425 url::SchemeHostPort server("https", "www.example.org", 443);
16426 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1416427
16428 // Negotiate HTTP/1.1 with alternative.
16429 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616430 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416431 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
16432
16433 // No data should be read from the alternative, because HTTP/1.1 is
16434 // negotiated.
16435 StaticSocketDataProvider data;
16436 session_deps_.socket_factory->AddSocketDataProvider(&data);
16437
zhongyi3d4a55e72016-04-22 20:36:4616438 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1416439 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616440 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416441 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
16442
16443 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2516444 MockWrite("GET / HTTP/1.1\r\n"
16445 "Host: www.example.org\r\n"
16446 "Connection: keep-alive\r\n\r\n"),
16447 MockWrite("GET /second HTTP/1.1\r\n"
16448 "Host: www.example.org\r\n"
16449 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1416450 };
16451
16452 MockRead http_reads[] = {
16453 MockRead("HTTP/1.1 200 OK\r\n"),
16454 MockRead("Content-Type: text/html\r\n"),
16455 MockRead("Content-Length: 6\r\n\r\n"),
16456 MockRead("foobar"),
16457 MockRead("HTTP/1.1 200 OK\r\n"),
16458 MockRead("Content-Type: text/html\r\n"),
16459 MockRead("Content-Length: 7\r\n\r\n"),
16460 MockRead("another"),
16461 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116462 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1416463 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16464
zhongyi3d4a55e72016-04-22 20:36:4616465 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916466 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016467 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1416468 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116469 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216470 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116471 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716472 server, NetworkIsolationKey(), alternative_service, expiration);
bnc40448a532015-05-11 19:13:1416473
16474 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16475 HttpRequestInfo request1;
16476 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2516477 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1416478 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016479 request1.traffic_annotation =
16480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416481 TestCompletionCallback callback1;
16482
tfarina42834112016-09-22 13:38:2016483 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416484 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116485 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416486
16487 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216488 ASSERT_TRUE(response1);
16489 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1416490 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
16491
16492 std::string response_data1;
robpercival214763f2016-07-01 23:27:0116493 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1416494 EXPECT_EQ("foobar", response_data1);
16495
16496 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
16497 // for alternative service.
Matt Menkeb32ba5122019-09-10 19:17:0516498 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
16499 alternative_service, NetworkIsolationKey()));
bnc40448a532015-05-11 19:13:1416500
zhongyi3d4a55e72016-04-22 20:36:4616501 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1416502 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4616503 // to server.
bnc40448a532015-05-11 19:13:1416504 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16505 HttpRequestInfo request2;
16506 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2516507 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1416508 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016509 request2.traffic_annotation =
16510 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416511 TestCompletionCallback callback2;
16512
tfarina42834112016-09-22 13:38:2016513 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416514 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116515 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416516
16517 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216518 ASSERT_TRUE(response2);
16519 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1416520 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
16521
16522 std::string response_data2;
robpercival214763f2016-07-01 23:27:0116523 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1416524 EXPECT_EQ("another", response_data2);
16525}
16526
bnc5452e2a2015-05-08 16:27:4216527// Alternative service requires HTTP/2 (or SPDY), but there is already a
16528// HTTP/1.1 socket open to the alternative server. That socket should not be
16529// used.
bncd16676a2016-07-20 16:23:0116530TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4616531 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4216532 HostPortPair alternative("alternative.example.org", 443);
16533 std::string origin_url = "https://origin.example.org:443";
16534 std::string alternative_url = "https://alternative.example.org:443";
16535
16536 // Negotiate HTTP/1.1 with alternative.example.org.
16537 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616538 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216539 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16540
16541 // HTTP/1.1 data for |request1| and |request2|.
16542 MockWrite http_writes[] = {
16543 MockWrite(
16544 "GET / HTTP/1.1\r\n"
16545 "Host: alternative.example.org\r\n"
16546 "Connection: keep-alive\r\n\r\n"),
16547 MockWrite(
16548 "GET / HTTP/1.1\r\n"
16549 "Host: alternative.example.org\r\n"
16550 "Connection: keep-alive\r\n\r\n"),
16551 };
16552
16553 MockRead http_reads[] = {
16554 MockRead(
16555 "HTTP/1.1 200 OK\r\n"
16556 "Content-Type: text/html; charset=iso-8859-1\r\n"
16557 "Content-Length: 40\r\n\r\n"
16558 "first HTTP/1.1 response from alternative"),
16559 MockRead(
16560 "HTTP/1.1 200 OK\r\n"
16561 "Content-Type: text/html; charset=iso-8859-1\r\n"
16562 "Content-Length: 41\r\n\r\n"
16563 "second HTTP/1.1 response from alternative"),
16564 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116565 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4216566 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16567
16568 // This test documents that an alternate Job should not pool to an already
16569 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4616570 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4216571 StaticSocketDataProvider data_refused;
16572 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16573 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16574
zhongyi3d4a55e72016-04-22 20:36:4616575 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916576 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016577 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216578 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116579 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216580 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116581 http_server_properties->SetHttp2AlternativeService(
Matt Menke9aa86262019-08-21 15:52:0716582 server, NetworkIsolationKey(), alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216583
16584 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4216585 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4616586 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216587 request1.method = "GET";
16588 request1.url = GURL(alternative_url);
16589 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016590 request1.traffic_annotation =
16591 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216592 TestCompletionCallback callback1;
16593
tfarina42834112016-09-22 13:38:2016594 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116595 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616596 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216597 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5216598 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4216599 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216600 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216601 EXPECT_FALSE(response1->was_fetched_via_spdy);
16602 std::string response_data1;
bnc691fda62016-08-12 00:43:1616603 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4216604 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
16605
16606 // Request for origin.example.org, which has an alternative service. This
16607 // will start two Jobs: the alternative looks for connections to pool to,
16608 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4616609 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4216610 // this request fails.
bnc5452e2a2015-05-08 16:27:4216611 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4616612 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216613 request2.method = "GET";
16614 request2.url = GURL(origin_url);
16615 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016616 request2.traffic_annotation =
16617 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216618 TestCompletionCallback callback2;
16619
tfarina42834112016-09-22 13:38:2016620 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116621 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4216622
16623 // Another transaction to alternative. This is to test that the HTTP/1.1
16624 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4216625 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4616626 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216627 request3.method = "GET";
16628 request3.url = GURL(alternative_url);
16629 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016630 request3.traffic_annotation =
16631 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216632 TestCompletionCallback callback3;
16633
tfarina42834112016-09-22 13:38:2016634 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116635 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616636 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216637 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5216638 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4216639 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216640 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216641 EXPECT_FALSE(response3->was_fetched_via_spdy);
16642 std::string response_data3;
bnc691fda62016-08-12 00:43:1616643 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4216644 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
16645}
16646
bncd16676a2016-07-20 16:23:0116647TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2316648 const std::string https_url = "https://www.example.org:8080/";
16649 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416650
rdsmithebb50aa2015-11-12 03:44:3816651 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0116652 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3816653
[email protected]8450d722012-07-02 19:14:0416654 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2316655 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0416656 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
16657 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
16658 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1316659 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916660 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316661 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0216662 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3916663
16664 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1316665 spdy::SpdyHeaderBlock req2_block;
16666 req2_block[spdy::kHttp2MethodHeader] = "GET";
16667 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
16668 req2_block[spdy::kHttp2SchemeHeader] = "http";
16669 req2_block[spdy::kHttp2PathHeader] = "/";
16670 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1516671 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0416672
16673 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116674 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
16675 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0416676 };
16677
Ryan Hamilton0239aac2018-05-19 00:03:1316678 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1516679 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316680 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1516681 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316682 spdy::SpdySerializedFrame body1(
16683 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
16684 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3816685 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316686 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3816687 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3516688 spdy::SpdySerializedFrame resp2(
16689 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316690 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3316691 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116692 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3316693 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4116694 CreateMockRead(wrapped_resp1, 4),
16695 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3316696 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4116697 CreateMockRead(resp2, 8),
16698 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3316699 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
16700 };
[email protected]8450d722012-07-02 19:14:0416701
Ryan Sleevib8d7ea02018-05-07 20:01:0116702 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416703 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716704 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416705
Lily Houghton8c2f97d2018-01-22 05:06:5916706 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4916707 ProxyResolutionService::CreateFixedFromPacResult(
16708 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116709 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716710 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0416711 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616712 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316713 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0416714 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616715 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16717 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0416718
danakj1fd259a02016-04-16 03:17:0916719 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0416720
16721 // Start the first transaction to set up the SpdySession
16722 HttpRequestInfo request1;
16723 request1.method = "GET";
16724 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416725 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016726 request1.traffic_annotation =
16727 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016728 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416729 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2016730 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416731
mmenke666a6fea2015-12-19 04:16:3316732 // This pause is a hack to avoid running into https://crbug.com/497228.
16733 data1.RunUntilPaused();
16734 base::RunLoop().RunUntilIdle();
16735 data1.Resume();
robpercival214763f2016-07-01 23:27:0116736 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0416737 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16738
[email protected]f6c63db52013-02-02 00:35:2216739 LoadTimingInfo load_timing_info1;
16740 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
16741 TestLoadTimingNotReusedWithPac(load_timing_info1,
16742 CONNECT_TIMING_HAS_SSL_TIMES);
16743
mmenke666a6fea2015-12-19 04:16:3316744 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0416745 HttpRequestInfo request2;
16746 request2.method = "GET";
16747 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416748 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016749 request2.traffic_annotation =
16750 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016751 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416752 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2016753 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416754
mmenke666a6fea2015-12-19 04:16:3316755 // This pause is a hack to avoid running into https://crbug.com/497228.
16756 data1.RunUntilPaused();
16757 base::RunLoop().RunUntilIdle();
16758 data1.Resume();
robpercival214763f2016-07-01 23:27:0116759 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3316760
[email protected]8450d722012-07-02 19:14:0416761 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2216762
16763 LoadTimingInfo load_timing_info2;
16764 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
16765 // The established SPDY sessions is considered reused by the HTTP request.
16766 TestLoadTimingReusedWithPac(load_timing_info2);
16767 // HTTP requests over a SPDY session should have a different connection
16768 // socket_log_id than requests over a tunnel.
16769 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0416770}
16771
[email protected]2d88e7d2012-07-19 17:55:1716772// Test that in the case where we have a SPDY session to a SPDY proxy
16773// that we do not pool other origins that resolve to the same IP when
16774// the certificate does not match the new origin.
16775// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0116776TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2316777 const std::string url1 = "http://www.example.org/";
16778 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1716779 const std::string ip_addr = "1.2.3.4";
16780
rdsmithebb50aa2015-11-12 03:44:3816781 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0116782 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3816783
[email protected]2d88e7d2012-07-19 17:55:1716784 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1316785 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2316786 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1316787 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1516788 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1716789
16790 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116791 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1716792 };
16793
Raul Tambre94493c652019-03-11 17:18:3516794 spdy::SpdySerializedFrame resp1(
16795 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316796 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1716797 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116798 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
16799 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1716800 };
16801
Ryan Sleevib8d7ea02018-05-07 20:01:0116802 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3216803 IPAddress ip;
martijn654c8c42016-02-10 22:10:5916804 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1716805 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16806 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3316807 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1716808
16809 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1316810 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916811 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1716812
16813 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116814 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1716815 };
16816
Ryan Hamilton0239aac2018-05-19 00:03:1316817 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3516818 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316819 spdy::SpdySerializedFrame body2(
16820 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116821 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3316822 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1716823
Ryan Sleevib8d7ea02018-05-07 20:01:0116824 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1716825 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3316826 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1716827
16828 // Set up a proxy config that sends HTTP requests to a proxy, and
16829 // all others direct.
16830 ProxyConfig proxy_config;
16831 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4916832 session_deps_.proxy_resolution_service =
16833 std::make_unique<ProxyResolutionService>(
16834 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
16835 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
16836 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1716837
bncce36dca22015-04-21 22:11:2316838 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616839 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1716840 // Load a valid cert. Note, that this does not need to
16841 // be valid for proxy because the MockSSLClientSocket does
16842 // not actually verify it. But SpdySession will use this
16843 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4916844 ssl1.ssl_info.cert =
16845 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
16846 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3316847 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16848 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1716849
16850 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616851 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316852 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16853 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1716854
Jeremy Roman0579ed62017-08-29 15:56:1916855 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2316856 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0716857 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1716858
danakj1fd259a02016-04-16 03:17:0916859 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1716860
16861 // Start the first transaction to set up the SpdySession
16862 HttpRequestInfo request1;
16863 request1.method = "GET";
16864 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1716865 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016866 request1.traffic_annotation =
16867 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016868 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716869 TestCompletionCallback callback1;
16870 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016871 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3316872 // This pause is a hack to avoid running into https://crbug.com/497228.
16873 data1.RunUntilPaused();
16874 base::RunLoop().RunUntilIdle();
16875 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1716876
robpercival214763f2016-07-01 23:27:0116877 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716878 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16879
16880 // Now, start the HTTP request
16881 HttpRequestInfo request2;
16882 request2.method = "GET";
16883 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1716884 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016885 request2.traffic_annotation =
16886 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016887 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716888 TestCompletionCallback callback2;
16889 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016890 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516891 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1716892
16893 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0116894 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716895 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16896}
16897
[email protected]85f97342013-04-17 06:12:2416898// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
16899// error) in SPDY session, removes the socket from pool and closes the SPDY
16900// session. Verify that new url's from the same HttpNetworkSession (and a new
16901// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0116902TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2316903 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2416904
16905 MockRead reads1[] = {
16906 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
16907 };
16908
Ryan Sleevib8d7ea02018-05-07 20:01:0116909 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2416910
Ryan Hamilton0239aac2018-05-19 00:03:1316911 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916912 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2416913 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116914 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2416915 };
16916
Raul Tambre94493c652019-03-11 17:18:3516917 spdy::SpdySerializedFrame resp2(
16918 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316919 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2416920 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4116921 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
16922 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2416923 };
16924
Ryan Sleevib8d7ea02018-05-07 20:01:0116925 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2416926
[email protected]85f97342013-04-17 06:12:2416927 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616928 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016929 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16930 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2416931
16932 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616933 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016934 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16935 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2416936
danakj1fd259a02016-04-16 03:17:0916937 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5016938 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2416939
16940 // Start the first transaction to set up the SpdySession and verify that
16941 // connection was closed.
16942 HttpRequestInfo request1;
16943 request1.method = "GET";
16944 request1.url = GURL(https_url);
16945 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016946 request1.traffic_annotation =
16947 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016948 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416949 TestCompletionCallback callback1;
16950 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016951 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0116952 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2416953
16954 // Now, start the second request and make sure it succeeds.
16955 HttpRequestInfo request2;
16956 request2.method = "GET";
16957 request2.url = GURL(https_url);
16958 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016959 request2.traffic_annotation =
16960 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016961 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416962 TestCompletionCallback callback2;
16963 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016964 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2416965
robpercival214763f2016-07-01 23:27:0116966 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2416967 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16968}
16969
bncd16676a2016-07-20 16:23:0116970TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0316971 ClientSocketPoolManager::set_max_sockets_per_group(
16972 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16973 ClientSocketPoolManager::set_max_sockets_per_pool(
16974 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16975
16976 // Use two different hosts with different IPs so they don't get pooled.
16977 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
16978 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0916979 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0316980
16981 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616982 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316983 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616984 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316985 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16986 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16987
Ryan Hamilton0239aac2018-05-19 00:03:1316988 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916989 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316990 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116991 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0316992 };
Ryan Hamilton0239aac2018-05-19 00:03:1316993 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516994 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316995 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116996 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316997 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116998 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916999 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317000 };
17001
rdsmithebb50aa2015-11-12 03:44:3817002 // Use a separate test instance for the separate SpdySession that will be
17003 // created.
bncd16676a2016-07-20 16:23:0117004 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0117005 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1217006 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0317007
Ryan Hamilton0239aac2018-05-19 00:03:1317008 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4917009 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0317010 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4117011 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0317012 };
Ryan Hamilton0239aac2018-05-19 00:03:1317013 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3517014 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1317015 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4117016 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0317017 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4117018 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5917019 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0317020 };
17021
Ryan Sleevib8d7ea02018-05-07 20:01:0117022 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1217023 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0317024
17025 MockWrite http_write[] = {
17026 MockWrite("GET / HTTP/1.1\r\n"
17027 "Host: www.a.com\r\n"
17028 "Connection: keep-alive\r\n\r\n"),
17029 };
17030
17031 MockRead http_read[] = {
17032 MockRead("HTTP/1.1 200 OK\r\n"),
17033 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
17034 MockRead("Content-Length: 6\r\n\r\n"),
17035 MockRead("hello!"),
17036 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117037 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0317038 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17039
17040 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117041 SpdySessionKey spdy_session_key_a(
17042 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
17043 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0317044 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617045 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317046
17047 TestCompletionCallback callback;
17048 HttpRequestInfo request1;
17049 request1.method = "GET";
17050 request1.url = GURL("https://www.a.com/");
17051 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017052 request1.traffic_annotation =
17053 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817054 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917055 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317056
tfarina42834112016-09-22 13:38:2017057 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117058 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17059 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317060
17061 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217062 ASSERT_TRUE(response);
17063 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217064 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317065 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217066 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0317067
17068 std::string response_data;
robpercival214763f2016-07-01 23:27:0117069 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317070 EXPECT_EQ("hello!", response_data);
17071 trans.reset();
17072 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617073 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317074
17075 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1117076 SpdySessionKey spdy_session_key_b(
17077 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
17078 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0317079 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617080 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317081 HttpRequestInfo request2;
17082 request2.method = "GET";
17083 request2.url = GURL("https://www.b.com/");
17084 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017085 request2.traffic_annotation =
17086 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817087 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917088 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317089
tfarina42834112016-09-22 13:38:2017090 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117091 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17092 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317093
17094 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217095 ASSERT_TRUE(response);
17096 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0217097 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0317098 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217099 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117100 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317101 EXPECT_EQ("hello!", response_data);
17102 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617103 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317104 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2617105 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317106
17107 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1117108 SpdySessionKey spdy_session_key_a1(
17109 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
17110 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0317111 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617112 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0317113 HttpRequestInfo request3;
17114 request3.method = "GET";
17115 request3.url = GURL("http://www.a.com/");
17116 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017117 request3.traffic_annotation =
17118 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5817119 trans =
Jeremy Roman0579ed62017-08-29 15:56:1917120 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0317121
tfarina42834112016-09-22 13:38:2017122 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117123 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17124 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0317125
17126 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5217127 ASSERT_TRUE(response);
17128 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0317129 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17130 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5217131 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0117132 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0317133 EXPECT_EQ("hello!", response_data);
17134 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617135 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0317136 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2617137 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0317138}
17139
bncd16676a2016-07-20 16:23:0117140TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417141 HttpRequestInfo request;
17142 request.method = "GET";
bncce36dca22015-04-21 22:11:2317143 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017144 request.traffic_annotation =
17145 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417146
danakj1fd259a02016-04-16 03:17:0917147 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617148 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417149
ttuttled9dbc652015-09-29 20:00:5917150 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417151 StaticSocketDataProvider data;
17152 data.set_connect_data(mock_connect);
17153 session_deps_.socket_factory->AddSocketDataProvider(&data);
17154
17155 TestCompletionCallback callback;
17156
tfarina42834112016-09-22 13:38:2017157 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117158 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417159
17160 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117161 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417162
ttuttle1f2d7e92015-04-28 16:17:4717163 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617164 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717165 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117166 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917167
17168 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617169 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917170 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417171}
17172
bncd16676a2016-07-20 16:23:0117173TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0417174 HttpRequestInfo request;
17175 request.method = "GET";
bncce36dca22015-04-21 22:11:2317176 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017177 request.traffic_annotation =
17178 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417179
danakj1fd259a02016-04-16 03:17:0917180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417182
ttuttled9dbc652015-09-29 20:00:5917183 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0417184 StaticSocketDataProvider data;
17185 data.set_connect_data(mock_connect);
17186 session_deps_.socket_factory->AddSocketDataProvider(&data);
17187
17188 TestCompletionCallback callback;
17189
tfarina42834112016-09-22 13:38:2017190 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117191 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417192
17193 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117194 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0417195
ttuttle1f2d7e92015-04-28 16:17:4717196 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1617197 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4717198 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0117199 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5917200
17201 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1617202 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5917203 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0417204}
17205
bncd16676a2016-07-20 16:23:0117206TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417207 HttpRequestInfo request;
17208 request.method = "GET";
bncce36dca22015-04-21 22:11:2317209 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017210 request.traffic_annotation =
17211 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417212
danakj1fd259a02016-04-16 03:17:0917213 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617214 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417215
17216 MockWrite data_writes[] = {
17217 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17218 };
17219 MockRead data_reads[] = {
17220 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17221 };
17222
Ryan Sleevib8d7ea02018-05-07 20:01:0117223 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417224 session_deps_.socket_factory->AddSocketDataProvider(&data);
17225
17226 TestCompletionCallback callback;
17227
tfarina42834112016-09-22 13:38:2017228 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117229 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417230
17231 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117232 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417233}
17234
bncd16676a2016-07-20 16:23:0117235TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0417236 HttpRequestInfo request;
17237 request.method = "GET";
bncce36dca22015-04-21 22:11:2317238 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017239 request.traffic_annotation =
17240 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417241
danakj1fd259a02016-04-16 03:17:0917242 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617243 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417244
17245 MockWrite data_writes[] = {
17246 MockWrite(ASYNC, ERR_CONNECTION_RESET),
17247 };
17248 MockRead data_reads[] = {
17249 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17250 };
17251
Ryan Sleevib8d7ea02018-05-07 20:01:0117252 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417253 session_deps_.socket_factory->AddSocketDataProvider(&data);
17254
17255 TestCompletionCallback callback;
17256
tfarina42834112016-09-22 13:38:2017257 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117258 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417259
17260 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117261 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417262}
17263
bncd16676a2016-07-20 16:23:0117264TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417265 HttpRequestInfo request;
17266 request.method = "GET";
bncce36dca22015-04-21 22:11:2317267 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017268 request.traffic_annotation =
17269 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417270
danakj1fd259a02016-04-16 03:17:0917271 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617272 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417273
17274 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317275 MockWrite(
17276 "GET / HTTP/1.1\r\n"
17277 "Host: www.example.org\r\n"
17278 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417279 };
17280 MockRead data_reads[] = {
17281 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
17282 };
17283
Ryan Sleevib8d7ea02018-05-07 20:01:0117284 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417285 session_deps_.socket_factory->AddSocketDataProvider(&data);
17286
17287 TestCompletionCallback callback;
17288
tfarina42834112016-09-22 13:38:2017289 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117290 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417291
17292 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117293 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417294}
17295
bncd16676a2016-07-20 16:23:0117296TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417297 HttpRequestInfo request;
17298 request.method = "GET";
bncce36dca22015-04-21 22:11:2317299 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017300 request.traffic_annotation =
17301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417302
danakj1fd259a02016-04-16 03:17:0917303 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617304 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417305
17306 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317307 MockWrite(
17308 "GET / HTTP/1.1\r\n"
17309 "Host: www.example.org\r\n"
17310 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417311 };
17312 MockRead data_reads[] = {
17313 MockRead(ASYNC, ERR_CONNECTION_RESET),
17314 };
17315
Ryan Sleevib8d7ea02018-05-07 20:01:0117316 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417317 session_deps_.socket_factory->AddSocketDataProvider(&data);
17318
17319 TestCompletionCallback callback;
17320
tfarina42834112016-09-22 13:38:2017321 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117322 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417323
17324 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117325 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417326}
17327
[email protected]043b68c82013-08-22 23:41:5217328// Tests that when a used socket is returned to the SSL socket pool, it's closed
17329// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117330TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5217331 ClientSocketPoolManager::set_max_sockets_per_group(
17332 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17333 ClientSocketPoolManager::set_max_sockets_per_pool(
17334 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17335
17336 // Set up SSL request.
17337
17338 HttpRequestInfo ssl_request;
17339 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2317340 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017341 ssl_request.traffic_annotation =
17342 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217343
17344 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2317345 MockWrite(
17346 "GET / HTTP/1.1\r\n"
17347 "Host: www.example.org\r\n"
17348 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217349 };
17350 MockRead ssl_reads[] = {
17351 MockRead("HTTP/1.1 200 OK\r\n"),
17352 MockRead("Content-Length: 11\r\n\r\n"),
17353 MockRead("hello world"),
17354 MockRead(SYNCHRONOUS, OK),
17355 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117356 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5217357 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17358
17359 SSLSocketDataProvider ssl(ASYNC, OK);
17360 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17361
17362 // Set up HTTP request.
17363
17364 HttpRequestInfo http_request;
17365 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317366 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017367 http_request.traffic_annotation =
17368 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217369
17370 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317371 MockWrite(
17372 "GET / HTTP/1.1\r\n"
17373 "Host: www.example.org\r\n"
17374 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217375 };
17376 MockRead http_reads[] = {
17377 MockRead("HTTP/1.1 200 OK\r\n"),
17378 MockRead("Content-Length: 7\r\n\r\n"),
17379 MockRead("falafel"),
17380 MockRead(SYNCHRONOUS, OK),
17381 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117382 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217383 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17384
danakj1fd259a02016-04-16 03:17:0917385 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217386
17387 // Start the SSL request.
17388 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1617389 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017390 ASSERT_EQ(ERR_IO_PENDING,
17391 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
17392 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5217393
17394 // Start the HTTP request. Pool should stall.
17395 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617396 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017397 ASSERT_EQ(ERR_IO_PENDING,
17398 http_trans.Start(&http_request, http_callback.callback(),
17399 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117400 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217401
17402 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0117403 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217404 std::string response_data;
bnc691fda62016-08-12 00:43:1617405 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217406 EXPECT_EQ("hello world", response_data);
17407
17408 // The SSL socket should automatically be closed, so the HTTP request can
17409 // start.
Matt Menke9d5e2c92019-02-05 01:42:2317410 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4117411 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217412
17413 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0117414 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1617415 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217416 EXPECT_EQ("falafel", response_data);
17417
dcheng48459ac22014-08-26 00:46:4117418 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217419}
17420
17421// Tests that when a SSL connection is established but there's no corresponding
17422// request that needs it, the new socket is closed if the transport socket pool
17423// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117424TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5217425 ClientSocketPoolManager::set_max_sockets_per_group(
17426 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17427 ClientSocketPoolManager::set_max_sockets_per_pool(
17428 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17429
17430 // Set up an ssl request.
17431
17432 HttpRequestInfo ssl_request;
17433 ssl_request.method = "GET";
17434 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1017435 ssl_request.traffic_annotation =
17436 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217437
17438 // No data will be sent on the SSL socket.
17439 StaticSocketDataProvider ssl_data;
17440 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17441
17442 SSLSocketDataProvider ssl(ASYNC, OK);
17443 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17444
17445 // Set up HTTP request.
17446
17447 HttpRequestInfo http_request;
17448 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317449 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017450 http_request.traffic_annotation =
17451 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217452
17453 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317454 MockWrite(
17455 "GET / HTTP/1.1\r\n"
17456 "Host: www.example.org\r\n"
17457 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217458 };
17459 MockRead http_reads[] = {
17460 MockRead("HTTP/1.1 200 OK\r\n"),
17461 MockRead("Content-Length: 7\r\n\r\n"),
17462 MockRead("falafel"),
17463 MockRead(SYNCHRONOUS, OK),
17464 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117465 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217466 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17467
danakj1fd259a02016-04-16 03:17:0917468 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217469
17470 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
17471 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2917472 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5917473 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2317474 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217475
17476 // Start the HTTP request. Pool should stall.
17477 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617478 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017479 ASSERT_EQ(ERR_IO_PENDING,
17480 http_trans.Start(&http_request, http_callback.callback(),
17481 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117482 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217483
17484 // The SSL connection will automatically be closed once the connection is
17485 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0117486 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217487 std::string response_data;
bnc691fda62016-08-12 00:43:1617488 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217489 EXPECT_EQ("falafel", response_data);
17490
dcheng48459ac22014-08-26 00:46:4117491 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217492}
17493
bncd16676a2016-07-20 16:23:0117494TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
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 request;
17501 request.method = "POST";
17502 request.url = GURL("http://www.foo.com/");
17503 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017504 request.traffic_annotation =
17505 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417506
danakj1fd259a02016-04-16 03:17:0917507 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617508 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417509 // Send headers successfully, but get an error while sending the body.
17510 MockWrite data_writes[] = {
17511 MockWrite("POST / HTTP/1.1\r\n"
17512 "Host: www.foo.com\r\n"
17513 "Connection: keep-alive\r\n"
17514 "Content-Length: 3\r\n\r\n"),
17515 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17516 };
17517
17518 MockRead data_reads[] = {
17519 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17520 MockRead("hello world"),
17521 MockRead(SYNCHRONOUS, OK),
17522 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117523 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417524 session_deps_.socket_factory->AddSocketDataProvider(&data);
17525
17526 TestCompletionCallback callback;
17527
tfarina42834112016-09-22 13:38:2017528 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117529 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417530
17531 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117532 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417533
bnc691fda62016-08-12 00:43:1617534 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217535 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417536
wezca1070932016-05-26 20:30:5217537 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417538 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17539
17540 std::string response_data;
bnc691fda62016-08-12 00:43:1617541 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117542 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417543 EXPECT_EQ("hello world", response_data);
17544}
17545
17546// This test makes sure the retry logic doesn't trigger when reading an error
17547// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0117548TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417549 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0917550 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5417551 MockWrite data_writes[] = {
17552 MockWrite("GET / HTTP/1.1\r\n"
17553 "Host: www.foo.com\r\n"
17554 "Connection: keep-alive\r\n\r\n"),
17555 MockWrite("POST / HTTP/1.1\r\n"
17556 "Host: www.foo.com\r\n"
17557 "Connection: keep-alive\r\n"
17558 "Content-Length: 3\r\n\r\n"),
17559 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17560 };
17561
17562 MockRead data_reads[] = {
17563 MockRead("HTTP/1.1 200 Peachy\r\n"
17564 "Content-Length: 14\r\n\r\n"),
17565 MockRead("first response"),
17566 MockRead("HTTP/1.1 400 Not OK\r\n"
17567 "Content-Length: 15\r\n\r\n"),
17568 MockRead("second response"),
17569 MockRead(SYNCHRONOUS, OK),
17570 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117571 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417572 session_deps_.socket_factory->AddSocketDataProvider(&data);
17573
17574 TestCompletionCallback callback;
17575 HttpRequestInfo request1;
17576 request1.method = "GET";
17577 request1.url = GURL("http://www.foo.com/");
17578 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017579 request1.traffic_annotation =
17580 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417581
bnc87dcefc2017-05-25 12:47:5817582 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1917583 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017584 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117585 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417586
17587 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117588 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417589
17590 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5217591 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5417592
wezca1070932016-05-26 20:30:5217593 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5417594 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
17595
17596 std::string response_data1;
17597 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0117598 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417599 EXPECT_EQ("first response", response_data1);
17600 // Delete the transaction to release the socket back into the socket pool.
17601 trans1.reset();
17602
danakj1fd259a02016-04-16 03:17:0917603 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217604 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917605 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217606 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417607
17608 HttpRequestInfo request2;
17609 request2.method = "POST";
17610 request2.url = GURL("http://www.foo.com/");
17611 request2.upload_data_stream = &upload_data_stream;
17612 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017613 request2.traffic_annotation =
17614 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417615
bnc691fda62016-08-12 00:43:1617616 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017617 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117618 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417619
17620 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117621 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417622
bnc691fda62016-08-12 00:43:1617623 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217624 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5417625
wezca1070932016-05-26 20:30:5217626 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5417627 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
17628
17629 std::string response_data2;
bnc691fda62016-08-12 00:43:1617630 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0117631 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417632 EXPECT_EQ("second response", response_data2);
17633}
17634
bncd16676a2016-07-20 16:23:0117635TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417636 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0917637 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217638 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917639 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217640 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417641
17642 HttpRequestInfo request;
17643 request.method = "POST";
17644 request.url = GURL("http://www.foo.com/");
17645 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017646 request.traffic_annotation =
17647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417648
danakj1fd259a02016-04-16 03:17:0917649 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617650 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417651 // Send headers successfully, but get an error while sending the body.
17652 MockWrite data_writes[] = {
17653 MockWrite("POST / HTTP/1.1\r\n"
17654 "Host: www.foo.com\r\n"
17655 "Connection: keep-alive\r\n"
17656 "Content-Length: 3\r\n\r\n"
17657 "fo"),
17658 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17659 };
17660
17661 MockRead data_reads[] = {
17662 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17663 MockRead("hello world"),
17664 MockRead(SYNCHRONOUS, OK),
17665 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117666 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417667 session_deps_.socket_factory->AddSocketDataProvider(&data);
17668
17669 TestCompletionCallback callback;
17670
tfarina42834112016-09-22 13:38:2017671 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117672 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417673
17674 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117675 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417676
bnc691fda62016-08-12 00:43:1617677 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217678 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417679
wezca1070932016-05-26 20:30:5217680 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417681 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17682
17683 std::string response_data;
bnc691fda62016-08-12 00:43:1617684 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117685 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417686 EXPECT_EQ("hello world", response_data);
17687}
17688
17689// This tests the more common case than the previous test, where headers and
17690// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0117691TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0717692 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5417693
17694 HttpRequestInfo request;
17695 request.method = "POST";
17696 request.url = GURL("http://www.foo.com/");
17697 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017698 request.traffic_annotation =
17699 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417700
danakj1fd259a02016-04-16 03:17:0917701 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617702 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417703 // Send headers successfully, but get an error while sending the body.
17704 MockWrite data_writes[] = {
17705 MockWrite("POST / HTTP/1.1\r\n"
17706 "Host: www.foo.com\r\n"
17707 "Connection: keep-alive\r\n"
17708 "Transfer-Encoding: chunked\r\n\r\n"),
17709 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17710 };
17711
17712 MockRead data_reads[] = {
17713 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17714 MockRead("hello world"),
17715 MockRead(SYNCHRONOUS, OK),
17716 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117717 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417718 session_deps_.socket_factory->AddSocketDataProvider(&data);
17719
17720 TestCompletionCallback callback;
17721
tfarina42834112016-09-22 13:38:2017722 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117723 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417724 // Make sure the headers are sent before adding a chunk. This ensures that
17725 // they can't be merged with the body in a single send. Not currently
17726 // necessary since a chunked body is never merged with headers, but this makes
17727 // the test more future proof.
17728 base::RunLoop().RunUntilIdle();
17729
mmenkecbc2b712014-10-09 20:29:0717730 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5417731
17732 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117733 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417734
bnc691fda62016-08-12 00:43:1617735 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217736 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417737
wezca1070932016-05-26 20:30:5217738 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417739 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17740
17741 std::string response_data;
bnc691fda62016-08-12 00:43:1617742 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117743 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417744 EXPECT_EQ("hello world", response_data);
17745}
17746
bncd16676a2016-07-20 16:23:0117747TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917748 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217749 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917750 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217751 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417752
17753 HttpRequestInfo request;
17754 request.method = "POST";
17755 request.url = GURL("http://www.foo.com/");
17756 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017757 request.traffic_annotation =
17758 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417759
danakj1fd259a02016-04-16 03:17:0917760 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617761 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417762
17763 MockWrite data_writes[] = {
17764 MockWrite("POST / HTTP/1.1\r\n"
17765 "Host: www.foo.com\r\n"
17766 "Connection: keep-alive\r\n"
17767 "Content-Length: 3\r\n\r\n"),
17768 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17769 };
17770
17771 MockRead data_reads[] = {
17772 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17773 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17774 MockRead("hello world"),
17775 MockRead(SYNCHRONOUS, OK),
17776 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117777 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417778 session_deps_.socket_factory->AddSocketDataProvider(&data);
17779
17780 TestCompletionCallback callback;
17781
tfarina42834112016-09-22 13:38:2017782 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117783 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417784
17785 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117786 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417787
bnc691fda62016-08-12 00:43:1617788 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217789 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417790
wezca1070932016-05-26 20:30:5217791 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417792 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17793
17794 std::string response_data;
bnc691fda62016-08-12 00:43:1617795 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117796 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417797 EXPECT_EQ("hello world", response_data);
17798}
17799
bncd16676a2016-07-20 16:23:0117800TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917801 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217802 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917803 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217804 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417805
17806 HttpRequestInfo request;
17807 request.method = "POST";
17808 request.url = GURL("http://www.foo.com/");
17809 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017810 request.traffic_annotation =
17811 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417812
danakj1fd259a02016-04-16 03:17:0917813 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617814 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417815 // Send headers successfully, but get an error while sending the body.
17816 MockWrite data_writes[] = {
17817 MockWrite("POST / HTTP/1.1\r\n"
17818 "Host: www.foo.com\r\n"
17819 "Connection: keep-alive\r\n"
17820 "Content-Length: 3\r\n\r\n"),
17821 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17822 };
17823
17824 MockRead data_reads[] = {
17825 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
17826 MockRead("hello world"),
17827 MockRead(SYNCHRONOUS, OK),
17828 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117829 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417830 session_deps_.socket_factory->AddSocketDataProvider(&data);
17831
17832 TestCompletionCallback callback;
17833
tfarina42834112016-09-22 13:38:2017834 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117835 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417836
17837 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117838 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417839}
17840
bncd16676a2016-07-20 16:23:0117841TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417842 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917843 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217844 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917845 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217846 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417847
17848 HttpRequestInfo request;
17849 request.method = "POST";
17850 request.url = GURL("http://www.foo.com/");
17851 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017852 request.traffic_annotation =
17853 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417854
danakj1fd259a02016-04-16 03:17:0917855 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617856 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417857 // Send headers successfully, but get an error while sending the body.
17858 MockWrite data_writes[] = {
17859 MockWrite("POST / HTTP/1.1\r\n"
17860 "Host: www.foo.com\r\n"
17861 "Connection: keep-alive\r\n"
17862 "Content-Length: 3\r\n\r\n"),
17863 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17864 };
17865
17866 MockRead data_reads[] = {
17867 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17868 MockRead("HTTP/1.0 302 Redirect\r\n"),
17869 MockRead("Location: http://somewhere-else.com/\r\n"),
17870 MockRead("Content-Length: 0\r\n\r\n"),
17871 MockRead(SYNCHRONOUS, OK),
17872 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117873 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417874 session_deps_.socket_factory->AddSocketDataProvider(&data);
17875
17876 TestCompletionCallback callback;
17877
tfarina42834112016-09-22 13:38:2017878 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117879 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417880
17881 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117882 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417883}
17884
bncd16676a2016-07-20 16:23:0117885TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917886 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217887 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917888 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217889 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417890
17891 HttpRequestInfo request;
17892 request.method = "POST";
17893 request.url = GURL("http://www.foo.com/");
17894 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017895 request.traffic_annotation =
17896 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417897
danakj1fd259a02016-04-16 03:17:0917898 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617899 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417900 // Send headers successfully, but get an error while sending the body.
17901 MockWrite data_writes[] = {
17902 MockWrite("POST / HTTP/1.1\r\n"
17903 "Host: www.foo.com\r\n"
17904 "Connection: keep-alive\r\n"
17905 "Content-Length: 3\r\n\r\n"),
17906 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17907 };
17908
17909 MockRead data_reads[] = {
17910 MockRead("HTTP 0.9 rocks!"),
17911 MockRead(SYNCHRONOUS, OK),
17912 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117913 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417914 session_deps_.socket_factory->AddSocketDataProvider(&data);
17915
17916 TestCompletionCallback callback;
17917
tfarina42834112016-09-22 13:38:2017918 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417920
17921 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117922 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417923}
17924
bncd16676a2016-07-20 16:23:0117925TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0917926 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217927 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917928 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217929 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417930
17931 HttpRequestInfo request;
17932 request.method = "POST";
17933 request.url = GURL("http://www.foo.com/");
17934 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017935 request.traffic_annotation =
17936 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417937
danakj1fd259a02016-04-16 03:17:0917938 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617939 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417940 // Send headers successfully, but get an error while sending the body.
17941 MockWrite data_writes[] = {
17942 MockWrite("POST / HTTP/1.1\r\n"
17943 "Host: www.foo.com\r\n"
17944 "Connection: keep-alive\r\n"
17945 "Content-Length: 3\r\n\r\n"),
17946 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17947 };
17948
17949 MockRead data_reads[] = {
17950 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
17951 MockRead(SYNCHRONOUS, OK),
17952 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117953 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417954 session_deps_.socket_factory->AddSocketDataProvider(&data);
17955
17956 TestCompletionCallback callback;
17957
tfarina42834112016-09-22 13:38:2017958 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117959 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417960
17961 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117962 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417963}
17964
Bence Békydca6bd92018-01-30 13:43:0617965#if BUILDFLAG(ENABLE_WEBSOCKETS)
17966
17967namespace {
17968
17969void AddWebSocketHeaders(HttpRequestHeaders* headers) {
17970 headers->SetHeader("Connection", "Upgrade");
17971 headers->SetHeader("Upgrade", "websocket");
17972 headers->SetHeader("Origin", "http://www.example.org");
17973 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0617974}
17975
17976} // namespace
17977
17978TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0117979 for (bool secure : {true, false}) {
17980 MockWrite data_writes[] = {
17981 MockWrite("GET / HTTP/1.1\r\n"
17982 "Host: www.example.org\r\n"
17983 "Connection: Upgrade\r\n"
17984 "Upgrade: websocket\r\n"
17985 "Origin: http://www.example.org\r\n"
17986 "Sec-WebSocket-Version: 13\r\n"
17987 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17988 "Sec-WebSocket-Extensions: permessage-deflate; "
17989 "client_max_window_bits\r\n\r\n")};
17990
17991 MockRead data_reads[] = {
17992 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17993 "Upgrade: websocket\r\n"
17994 "Connection: Upgrade\r\n"
17995 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
17996
Ryan Sleevib8d7ea02018-05-07 20:01:0117997 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0117998 session_deps_.socket_factory->AddSocketDataProvider(&data);
17999 SSLSocketDataProvider ssl(ASYNC, OK);
18000 if (secure)
18001 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0618002
18003 HttpRequestInfo request;
18004 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0118005 request.url =
18006 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18007 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1018008 request.traffic_annotation =
18009 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0618010
Bence Béky2fcf4fa2018-04-06 20:06:0118011 TestWebSocketHandshakeStreamCreateHelper
18012 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1518013
Bence Béky2fcf4fa2018-04-06 20:06:0118014 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0618015 HttpNetworkTransaction trans(LOW, session.get());
18016 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0118017 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0618018
18019 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0118020 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18021 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0618022
Bence Béky2fcf4fa2018-04-06 20:06:0118023 const HttpStreamRequest* stream_request = trans.stream_request_.get();
18024 ASSERT_TRUE(stream_request);
18025 EXPECT_EQ(&websocket_handshake_stream_create_helper,
18026 stream_request->websocket_handshake_stream_create_helper());
18027
18028 rv = callback.WaitForResult();
18029 EXPECT_THAT(rv, IsOk());
18030
18031 EXPECT_TRUE(data.AllReadDataConsumed());
18032 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0618033 }
18034}
18035
Adam Rice425cf122015-01-19 06:18:2418036// Verify that proxy headers are not sent to the destination server when
18037// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0118038TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2418039 HttpRequestInfo request;
18040 request.method = "GET";
bncce36dca22015-04-21 22:11:2318041 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018042 request.traffic_annotation =
18043 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418044 AddWebSocketHeaders(&request.extra_headers);
18045
18046 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918047 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918048 ProxyResolutionService::CreateFixedFromPacResult(
18049 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418050
danakj1fd259a02016-04-16 03:17:0918051 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418052
18053 // Since a proxy is configured, try to establish a tunnel.
18054 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1718055 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18056 "Host: www.example.org:443\r\n"
18057 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418058
18059 // After calling trans->RestartWithAuth(), this is the request we should
18060 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1718061 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18062 "Host: www.example.org:443\r\n"
18063 "Proxy-Connection: keep-alive\r\n"
18064 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418065
rsleevidb16bb02015-11-12 23:47:1718066 MockWrite("GET / HTTP/1.1\r\n"
18067 "Host: www.example.org\r\n"
18068 "Connection: Upgrade\r\n"
18069 "Upgrade: websocket\r\n"
18070 "Origin: http://www.example.org\r\n"
18071 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1518072 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18073 "Sec-WebSocket-Extensions: permessage-deflate; "
18074 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418075
18076 // The proxy responds to the connect with a 407, using a persistent
18077 // connection.
18078 MockRead data_reads[] = {
18079 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1518080 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
18081 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
18082 "Content-Length: 0\r\n"
18083 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418084
18085 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18086
Bence Béky8d1c6052018-02-07 12:48:1518087 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18088 "Upgrade: websocket\r\n"
18089 "Connection: Upgrade\r\n"
18090 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418091
Ryan Sleevib8d7ea02018-05-07 20:01:0118092 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418093 session_deps_.socket_factory->AddSocketDataProvider(&data);
18094 SSLSocketDataProvider ssl(ASYNC, OK);
18095 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18096
Bence Béky8d1c6052018-02-07 12:48:1518097 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18098
bnc87dcefc2017-05-25 12:47:5818099 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918100 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418101 trans->SetWebSocketHandshakeStreamCreateHelper(
18102 &websocket_stream_create_helper);
18103
18104 {
18105 TestCompletionCallback callback;
18106
tfarina42834112016-09-22 13:38:2018107 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118108 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418109
18110 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118111 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418112 }
18113
18114 const HttpResponseInfo* response = trans->GetResponseInfo();
18115 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218116 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418117 EXPECT_EQ(407, response->headers->response_code());
18118
18119 {
18120 TestCompletionCallback callback;
18121
18122 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
18123 callback.callback());
robpercival214763f2016-07-01 23:27:0118124 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418125
18126 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118127 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418128 }
18129
18130 response = trans->GetResponseInfo();
18131 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218132 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418133
18134 EXPECT_EQ(101, response->headers->response_code());
18135
18136 trans.reset();
18137 session->CloseAllConnections();
18138}
18139
18140// Verify that proxy headers are not sent to the destination server when
18141// establishing a tunnel for an insecure WebSocket connection.
18142// This requires the authentication info to be injected into the auth cache
18143// due to crbug.com/395064
18144// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0118145TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2418146 HttpRequestInfo request;
18147 request.method = "GET";
bncce36dca22015-04-21 22:11:2318148 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018149 request.traffic_annotation =
18150 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418151 AddWebSocketHeaders(&request.extra_headers);
18152
18153 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5918154 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918155 ProxyResolutionService::CreateFixedFromPacResult(
18156 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2418157
danakj1fd259a02016-04-16 03:17:0918158 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2418159
18160 MockWrite data_writes[] = {
18161 // Try to establish a tunnel for the WebSocket connection, with
18162 // credentials. Because WebSockets have a separate set of socket pools,
18163 // they cannot and will not use the same TCP/IP connection as the
18164 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1518165 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
18166 "Host: www.example.org:80\r\n"
18167 "Proxy-Connection: keep-alive\r\n"
18168 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2418169
Bence Béky8d1c6052018-02-07 12:48:1518170 MockWrite("GET / HTTP/1.1\r\n"
18171 "Host: www.example.org\r\n"
18172 "Connection: Upgrade\r\n"
18173 "Upgrade: websocket\r\n"
18174 "Origin: http://www.example.org\r\n"
18175 "Sec-WebSocket-Version: 13\r\n"
18176 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
18177 "Sec-WebSocket-Extensions: permessage-deflate; "
18178 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418179
18180 MockRead data_reads[] = {
18181 // HTTP CONNECT with credentials.
18182 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18183
18184 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1518185 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18186 "Upgrade: websocket\r\n"
18187 "Connection: Upgrade\r\n"
18188 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418189
Ryan Sleevib8d7ea02018-05-07 20:01:0118190 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418191 session_deps_.socket_factory->AddSocketDataProvider(&data);
18192
18193 session->http_auth_cache()->Add(
18194 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
18195 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
18196
Bence Béky8d1c6052018-02-07 12:48:1518197 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18198
bnc87dcefc2017-05-25 12:47:5818199 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918200 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418201 trans->SetWebSocketHandshakeStreamCreateHelper(
18202 &websocket_stream_create_helper);
18203
18204 TestCompletionCallback callback;
18205
tfarina42834112016-09-22 13:38:2018206 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118207 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418208
18209 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118210 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418211
18212 const HttpResponseInfo* response = trans->GetResponseInfo();
18213 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218214 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418215
18216 EXPECT_EQ(101, response->headers->response_code());
18217
18218 trans.reset();
18219 session->CloseAllConnections();
18220}
18221
Matt Menke1d6093e32019-03-22 17:33:4318222// WebSockets over QUIC is not supported, including over QUIC proxies.
18223TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18224 for (bool secure : {true, false}) {
18225 SCOPED_TRACE(secure);
18226 session_deps_.proxy_resolution_service =
18227 ProxyResolutionService::CreateFixedFromPacResult(
18228 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18229 session_deps_.enable_quic = true;
18230
18231 HttpRequestInfo request;
18232 request.url =
18233 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18234 AddWebSocketHeaders(&request.extra_headers);
18235 request.traffic_annotation =
18236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18237
18238 TestWebSocketHandshakeStreamCreateHelper
18239 websocket_handshake_stream_create_helper;
18240
18241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18242 HttpNetworkTransaction trans(LOW, session.get());
18243 trans.SetWebSocketHandshakeStreamCreateHelper(
18244 &websocket_handshake_stream_create_helper);
18245
18246 TestCompletionCallback callback;
18247 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18248 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18249
18250 rv = callback.WaitForResult();
18251 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18252 }
18253}
18254
Bence Békydca6bd92018-01-30 13:43:0618255#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18256
bncd16676a2016-07-20 16:23:0118257TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918258 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218259 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918260 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218261 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218262
18263 HttpRequestInfo request;
18264 request.method = "POST";
18265 request.url = GURL("http://www.foo.com/");
18266 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018267 request.traffic_annotation =
18268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218269
danakj1fd259a02016-04-16 03:17:0918270 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618271 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218272 MockWrite data_writes[] = {
18273 MockWrite("POST / HTTP/1.1\r\n"
18274 "Host: www.foo.com\r\n"
18275 "Connection: keep-alive\r\n"
18276 "Content-Length: 3\r\n\r\n"),
18277 MockWrite("foo"),
18278 };
18279
18280 MockRead data_reads[] = {
18281 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18282 MockRead(SYNCHRONOUS, OK),
18283 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118284 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218285 session_deps_.socket_factory->AddSocketDataProvider(&data);
18286
18287 TestCompletionCallback callback;
18288
18289 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018290 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118291 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218292
18293 std::string response_data;
bnc691fda62016-08-12 00:43:1618294 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218295
Ryan Sleevib8d7ea02018-05-07 20:01:0118296 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18297 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218298}
18299
bncd16676a2016-07-20 16:23:0118300TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0918301 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218302 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918303 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218304 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218305
18306 HttpRequestInfo request;
18307 request.method = "POST";
18308 request.url = GURL("http://www.foo.com/");
18309 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018310 request.traffic_annotation =
18311 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218312
danakj1fd259a02016-04-16 03:17:0918313 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618314 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218315 MockWrite data_writes[] = {
18316 MockWrite("POST / HTTP/1.1\r\n"
18317 "Host: www.foo.com\r\n"
18318 "Connection: keep-alive\r\n"
18319 "Content-Length: 3\r\n\r\n"),
18320 MockWrite("foo"),
18321 };
18322
18323 MockRead data_reads[] = {
18324 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
18325 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18326 MockRead(SYNCHRONOUS, OK),
18327 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118328 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218329 session_deps_.socket_factory->AddSocketDataProvider(&data);
18330
18331 TestCompletionCallback callback;
18332
18333 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018334 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118335 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218336
18337 std::string response_data;
bnc691fda62016-08-12 00:43:1618338 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218339
Ryan Sleevib8d7ea02018-05-07 20:01:0118340 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18341 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218342}
18343
bncd16676a2016-07-20 16:23:0118344TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2218345 ChunkedUploadDataStream upload_data_stream(0);
18346
18347 HttpRequestInfo request;
18348 request.method = "POST";
18349 request.url = GURL("http://www.foo.com/");
18350 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018351 request.traffic_annotation =
18352 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218353
danakj1fd259a02016-04-16 03:17:0918354 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618355 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218356 // Send headers successfully, but get an error while sending the body.
18357 MockWrite data_writes[] = {
18358 MockWrite("POST / HTTP/1.1\r\n"
18359 "Host: www.foo.com\r\n"
18360 "Connection: keep-alive\r\n"
18361 "Transfer-Encoding: chunked\r\n\r\n"),
18362 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
18363 };
18364
18365 MockRead data_reads[] = {
18366 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18367 MockRead(SYNCHRONOUS, OK),
18368 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118369 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218370 session_deps_.socket_factory->AddSocketDataProvider(&data);
18371
18372 TestCompletionCallback callback;
18373
18374 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018375 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2218376
18377 base::RunLoop().RunUntilIdle();
18378 upload_data_stream.AppendData("f", 1, false);
18379
18380 base::RunLoop().RunUntilIdle();
18381 upload_data_stream.AppendData("oo", 2, true);
18382
robpercival214763f2016-07-01 23:27:0118383 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218384
18385 std::string response_data;
bnc691fda62016-08-12 00:43:1618386 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218387
Ryan Sleevib8d7ea02018-05-07 20:01:0118388 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18389 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218390}
18391
eustasc7d27da2017-04-06 10:33:2018392void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
18393 const std::string& accept_encoding,
18394 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0318395 const std::string& location,
eustasc7d27da2017-04-06 10:33:2018396 bool should_match) {
18397 HttpRequestInfo request;
18398 request.method = "GET";
18399 request.url = GURL("http://www.foo.com/");
18400 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
18401 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1018402 request.traffic_annotation =
18403 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2018404
18405 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
18406 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18407 // Send headers successfully, but get an error while sending the body.
18408 MockWrite data_writes[] = {
18409 MockWrite("GET / HTTP/1.1\r\n"
18410 "Host: www.foo.com\r\n"
18411 "Connection: keep-alive\r\n"
18412 "Accept-Encoding: "),
18413 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
18414 };
18415
sky50576f32017-05-01 19:28:0318416 std::string response_code = "200 OK";
18417 std::string extra;
18418 if (!location.empty()) {
18419 response_code = "301 Redirect\r\nLocation: ";
18420 response_code.append(location);
18421 }
18422
eustasc7d27da2017-04-06 10:33:2018423 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0318424 MockRead("HTTP/1.0 "),
18425 MockRead(response_code.data()),
18426 MockRead("\r\nContent-Encoding: "),
18427 MockRead(content_encoding.data()),
18428 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2018429 MockRead(SYNCHRONOUS, OK),
18430 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118431 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2018432 session_deps->socket_factory->AddSocketDataProvider(&data);
18433
18434 TestCompletionCallback callback;
18435
18436 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18437 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18438
18439 rv = callback.WaitForResult();
18440 if (should_match) {
18441 EXPECT_THAT(rv, IsOk());
18442 } else {
18443 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
18444 }
18445}
18446
18447TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0318448 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2018449}
18450
18451TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0318452 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
18453 true);
eustasc7d27da2017-04-06 10:33:2018454}
18455
18456TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
18457 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0318458 "", false);
18459}
18460
18461TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
18462 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
18463 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2018464}
18465
xunjieli96f2a402017-06-05 17:24:2718466TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
18467 ProxyConfig proxy_config;
18468 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18469 proxy_config.set_pac_mandatory(true);
18470 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918471 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918472 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18473 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0418474 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2718475
18476 HttpRequestInfo request;
18477 request.method = "GET";
18478 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018479 request.traffic_annotation =
18480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718481
18482 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18483 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18484
18485 TestCompletionCallback callback;
18486
18487 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18488 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18489 EXPECT_THAT(callback.WaitForResult(),
18490 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18491}
18492
18493TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
18494 ProxyConfig proxy_config;
18495 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18496 proxy_config.set_pac_mandatory(true);
18497 MockAsyncProxyResolverFactory* proxy_resolver_factory =
18498 new MockAsyncProxyResolverFactory(false);
18499 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918500 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918501 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18502 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5918503 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2718504 HttpRequestInfo request;
18505 request.method = "GET";
18506 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018507 request.traffic_annotation =
18508 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718509
18510 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18511 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18512
18513 TestCompletionCallback callback;
18514 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18515 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18516
18517 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
18518 ERR_FAILED, &resolver);
18519 EXPECT_THAT(callback.WaitForResult(),
18520 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18521}
18522
18523TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5918524 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918525 ProxyResolutionService::CreateFixedFromPacResult(
18526 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718527 session_deps_.enable_quic = false;
18528 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18529
18530 HttpRequestInfo request;
18531 request.method = "GET";
18532 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018533 request.traffic_annotation =
18534 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718535
18536 TestCompletionCallback callback;
18537 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18538 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18539 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18540
18541 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
18542}
18543
Douglas Creager3cb042052018-11-06 23:08:5218544//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1418545// Reporting tests
18546
18547#if BUILDFLAG(ENABLE_REPORTING)
18548class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
18549 protected:
18550 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618551 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1418552 auto test_reporting_context = std::make_unique<TestReportingContext>(
18553 &clock_, &tick_clock_, ReportingPolicy());
18554 test_reporting_context_ = test_reporting_context.get();
18555 session_deps_.reporting_service =
18556 ReportingService::CreateForTesting(std::move(test_reporting_context));
18557 }
18558
18559 TestReportingContext* reporting_context() const {
18560 return test_reporting_context_;
18561 }
18562
18563 void clear_reporting_service() {
18564 session_deps_.reporting_service.reset();
18565 test_reporting_context_ = nullptr;
18566 }
18567
18568 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4218569 void RequestPolicy(CertStatus cert_status = 0) {
18570 HttpRequestInfo request;
18571 request.method = "GET";
18572 request.url = GURL(url_);
18573 request.traffic_annotation =
18574 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18575
Lily Chend3930e72019-03-01 19:31:1118576 MockWrite data_writes[] = {
18577 MockWrite("GET / HTTP/1.1\r\n"
18578 "Host: www.example.org\r\n"
18579 "Connection: keep-alive\r\n\r\n"),
18580 };
Douglas Creager134b52e2018-11-09 18:00:1418581 MockRead data_reads[] = {
18582 MockRead("HTTP/1.0 200 OK\r\n"),
18583 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
18584 "\"endpoints\": [{\"url\": "
18585 "\"https://www.example.org/upload/\"}]}\r\n"),
18586 MockRead("\r\n"),
18587 MockRead("hello world"),
18588 MockRead(SYNCHRONOUS, OK),
18589 };
Douglas Creager134b52e2018-11-09 18:00:1418590
Lily Chenfec60d92019-01-24 01:16:4218591 StaticSocketDataProvider reads(data_reads, data_writes);
18592 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1418593
18594 SSLSocketDataProvider ssl(ASYNC, OK);
18595 if (request.url.SchemeIsCryptographic()) {
18596 ssl.ssl_info.cert =
18597 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18598 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218599 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1418600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18601 }
18602
Douglas Creager134b52e2018-11-09 18:00:1418603 TestCompletionCallback callback;
18604 auto session = CreateSession(&session_deps_);
18605 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18606 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4218607 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1418608 }
18609
18610 protected:
18611 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1418612
18613 private:
18614 TestReportingContext* test_reporting_context_;
18615};
18616
18617TEST_F(HttpNetworkTransactionReportingTest,
18618 DontProcessReportToHeaderNoService) {
18619 base::HistogramTester histograms;
18620 clear_reporting_service();
18621 RequestPolicy();
18622 histograms.ExpectBucketCount(
18623 ReportingHeaderParser::kHeaderOutcomeHistogram,
18624 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
18625}
18626
18627TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
18628 base::HistogramTester histograms;
18629 url_ = "http://www.example.org/";
18630 RequestPolicy();
18631 histograms.ExpectBucketCount(
18632 ReportingHeaderParser::kHeaderOutcomeHistogram,
18633 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18634}
18635
18636TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
18637 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5418638 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1018639 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5418640 reporting_context()->cache()->GetEndpointForTesting(
18641 url::Origin::Create(GURL("https://www.example.org/")), "nel",
18642 GURL("https://www.example.org/upload/"));
18643 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1418644}
18645
18646TEST_F(HttpNetworkTransactionReportingTest,
18647 DontProcessReportToHeaderInvalidHttps) {
18648 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218649 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18650 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1418651 histograms.ExpectBucketCount(
18652 ReportingHeaderParser::kHeaderOutcomeHistogram,
18653 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
18654}
18655#endif // BUILDFLAG(ENABLE_REPORTING)
18656
18657//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5218658// Network Error Logging tests
18659
18660#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4218661namespace {
18662
18663const char kUserAgent[] = "Mozilla/1.0";
18664const char kReferrer[] = "https://www.referrer.org/";
18665
18666} // namespace
18667
Douglas Creager3cb042052018-11-06 23:08:5218668class HttpNetworkTransactionNetworkErrorLoggingTest
18669 : public HttpNetworkTransactionTest {
18670 protected:
18671 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618672 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5218673 auto network_error_logging_service =
18674 std::make_unique<TestNetworkErrorLoggingService>();
18675 test_network_error_logging_service_ = network_error_logging_service.get();
18676 session_deps_.network_error_logging_service =
18677 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4218678
18679 extra_headers_.SetHeader("User-Agent", kUserAgent);
18680 extra_headers_.SetHeader("Referer", kReferrer);
18681
18682 request_.method = "GET";
18683 request_.url = GURL(url_);
18684 request_.extra_headers = extra_headers_;
18685 request_.reporting_upload_depth = reporting_upload_depth_;
18686 request_.traffic_annotation =
18687 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5218688 }
18689
18690 TestNetworkErrorLoggingService* network_error_logging_service() const {
18691 return test_network_error_logging_service_;
18692 }
18693
18694 void clear_network_error_logging_service() {
18695 session_deps_.network_error_logging_service.reset();
18696 test_network_error_logging_service_ = nullptr;
18697 }
18698
18699 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4218700 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3618701 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318702 MockWrite data_writes[] = {
18703 MockWrite("GET / HTTP/1.1\r\n"
18704 "Host: www.example.org\r\n"
18705 "Connection: keep-alive\r\n"),
18706 MockWrite(ASYNC, extra_header_string.data(),
18707 extra_header_string.size()),
18708 };
Lily Chend3930e72019-03-01 19:31:1118709 MockRead data_reads[] = {
18710 MockRead("HTTP/1.0 200 OK\r\n"),
18711 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18712 MockRead("\r\n"),
18713 MockRead("hello world"),
18714 MockRead(SYNCHRONOUS, OK),
18715 };
Douglas Creager3cb042052018-11-06 23:08:5218716
Lily Chenfec60d92019-01-24 01:16:4218717 StaticSocketDataProvider reads(data_reads, data_writes);
18718 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5218719
18720 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4218721 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5218722 ssl.ssl_info.cert =
18723 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18724 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218725 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5218726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18727 }
18728
Douglas Creager3cb042052018-11-06 23:08:5218729 TestCompletionCallback callback;
18730 auto session = CreateSession(&session_deps_);
18731 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4218732 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
18733 EXPECT_THAT(callback.GetResult(rv), IsOk());
18734
18735 std::string response_data;
18736 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18737 EXPECT_EQ("hello world", response_data);
18738 }
18739
18740 void CheckReport(size_t index,
18741 int status_code,
18742 int error_type,
18743 IPAddress server_ip = IPAddress::IPv4Localhost()) {
18744 ASSERT_LT(index, network_error_logging_service()->errors().size());
18745
18746 const NetworkErrorLoggingService::RequestDetails& error =
18747 network_error_logging_service()->errors()[index];
18748 EXPECT_EQ(url_, error.uri);
18749 EXPECT_EQ(kReferrer, error.referrer);
18750 EXPECT_EQ(kUserAgent, error.user_agent);
18751 EXPECT_EQ(server_ip, error.server_ip);
18752 EXPECT_EQ("http/1.1", error.protocol);
18753 EXPECT_EQ("GET", error.method);
18754 EXPECT_EQ(status_code, error.status_code);
18755 EXPECT_EQ(error_type, error.type);
18756 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5218757 }
18758
18759 protected:
18760 std::string url_ = "https://www.example.org/";
18761 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4218762 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3618763 HttpRequestHeaders extra_headers_;
18764 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5218765
18766 private:
18767 TestNetworkErrorLoggingService* test_network_error_logging_service_;
18768};
18769
18770TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18771 DontProcessNelHeaderNoService) {
18772 base::HistogramTester histograms;
18773 clear_network_error_logging_service();
18774 RequestPolicy();
18775 histograms.ExpectBucketCount(
18776 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18777 NetworkErrorLoggingService::HeaderOutcome::
18778 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
18779 1);
18780}
18781
18782TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18783 DontProcessNelHeaderHttp) {
18784 base::HistogramTester histograms;
18785 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4218786 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5218787 RequestPolicy();
18788 histograms.ExpectBucketCount(
18789 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18790 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18791}
18792
Lily Chen90ae93cc2019-02-14 01:15:3918793// Don't set NEL policies received on a proxied connection.
18794TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18795 DontProcessNelHeaderProxy) {
18796 session_deps_.proxy_resolution_service =
18797 ProxyResolutionService::CreateFixedFromPacResult(
18798 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
18799 BoundTestNetLog log;
18800 session_deps_.net_log = log.bound().net_log();
18801 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18802
18803 HttpRequestInfo request;
18804 request.method = "GET";
18805 request.url = GURL("https://www.example.org/");
18806 request.traffic_annotation =
18807 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18808
18809 // Since we have proxy, should try to establish tunnel.
18810 MockWrite data_writes1[] = {
18811 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18812 "Host: www.example.org:443\r\n"
18813 "Proxy-Connection: keep-alive\r\n\r\n"),
18814
18815 MockWrite("GET / HTTP/1.1\r\n"
18816 "Host: www.example.org\r\n"
18817 "Connection: keep-alive\r\n\r\n"),
18818 };
18819
18820 MockRead data_reads1[] = {
18821 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18822
18823 MockRead("HTTP/1.1 200 OK\r\n"),
18824 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18825 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18826 MockRead("Content-Length: 100\r\n\r\n"),
18827 MockRead(SYNCHRONOUS, OK),
18828 };
18829
18830 StaticSocketDataProvider data1(data_reads1, data_writes1);
18831 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18832 SSLSocketDataProvider ssl(ASYNC, OK);
18833 ssl.ssl_info.cert =
18834 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18835 ASSERT_TRUE(ssl.ssl_info.cert);
18836 ssl.ssl_info.cert_status = 0;
18837 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18838
18839 TestCompletionCallback callback1;
18840 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18841
18842 int rv = trans.Start(&request, callback1.callback(), log.bound());
18843 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18844
18845 rv = callback1.WaitForResult();
18846 EXPECT_THAT(rv, IsOk());
18847
18848 const HttpResponseInfo* response = trans.GetResponseInfo();
18849 ASSERT_TRUE(response);
18850 EXPECT_EQ(200, response->headers->response_code());
18851 EXPECT_TRUE(response->was_fetched_via_proxy);
18852
18853 // No NEL header was set.
18854 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
18855}
18856
Douglas Creager3cb042052018-11-06 23:08:5218857TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
18858 RequestPolicy();
18859 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
18860 const auto& header = network_error_logging_service()->headers()[0];
18861 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
18862 header.origin);
18863 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
18864 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
18865}
18866
18867TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18868 DontProcessNelHeaderInvalidHttps) {
18869 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218870 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18871 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5218872 histograms.ExpectBucketCount(
18873 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18874 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
18875 1);
18876}
Douglas Creageref5eecdc2018-11-09 20:50:3618877
Lily Chenfec60d92019-01-24 01:16:4218878TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3618879 RequestPolicy();
18880 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4218881 CheckReport(0 /* index */, 200 /* status_code */, OK);
18882}
18883
18884TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18885 CreateReportErrorAfterStart) {
18886 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18887 auto trans =
18888 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18889
18890 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
18891 StaticSocketDataProvider data;
18892 data.set_connect_data(mock_connect);
18893 session_deps_.socket_factory->AddSocketDataProvider(&data);
18894
18895 TestCompletionCallback callback;
18896
18897 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18898 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18899
18900 trans.reset();
18901
18902 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18903 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18904 IPAddress() /* server_ip */);
18905}
18906
18907// Same as above except the error is ASYNC
18908TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18909 CreateReportErrorAfterStartAsync) {
18910 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18911 auto trans =
18912 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18913
18914 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
18915 StaticSocketDataProvider data;
18916 data.set_connect_data(mock_connect);
18917 session_deps_.socket_factory->AddSocketDataProvider(&data);
18918
18919 TestCompletionCallback callback;
18920
18921 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18922 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18923
18924 trans.reset();
18925
18926 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18927 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18928 IPAddress() /* server_ip */);
18929}
18930
18931TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18932 CreateReportReadBodyError) {
18933 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318934 MockWrite data_writes[] = {
18935 MockWrite("GET / HTTP/1.1\r\n"
18936 "Host: www.example.org\r\n"
18937 "Connection: keep-alive\r\n"),
18938 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18939 };
Lily Chend3930e72019-03-01 19:31:1118940 MockRead data_reads[] = {
18941 MockRead("HTTP/1.0 200 OK\r\n"),
18942 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18943 MockRead("hello world"),
18944 MockRead(SYNCHRONOUS, OK),
18945 };
Lily Chenfec60d92019-01-24 01:16:4218946
18947 StaticSocketDataProvider reads(data_reads, data_writes);
18948 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18949
18950 SSLSocketDataProvider ssl(ASYNC, OK);
18951 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18952
18953 // Log start time
18954 base::TimeTicks start_time = base::TimeTicks::Now();
18955
18956 TestCompletionCallback callback;
18957 auto session = CreateSession(&session_deps_);
18958 auto trans =
18959 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18960 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18961 EXPECT_THAT(callback.GetResult(rv), IsOk());
18962
18963 const HttpResponseInfo* response = trans->GetResponseInfo();
18964 ASSERT_TRUE(response);
18965
18966 EXPECT_TRUE(response->headers);
18967 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18968
18969 std::string response_data;
18970 rv = ReadTransaction(trans.get(), &response_data);
18971 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18972
18973 trans.reset();
18974
18975 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18976
18977 CheckReport(0 /* index */, 200 /* status_code */,
18978 ERR_CONTENT_LENGTH_MISMATCH);
18979 const NetworkErrorLoggingService::RequestDetails& error =
18980 network_error_logging_service()->errors()[0];
18981 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18982}
18983
18984// Same as above except the final read is ASYNC.
18985TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18986 CreateReportReadBodyErrorAsync) {
18987 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318988 MockWrite data_writes[] = {
18989 MockWrite("GET / HTTP/1.1\r\n"
18990 "Host: www.example.org\r\n"
18991 "Connection: keep-alive\r\n"),
18992 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18993 };
Lily Chend3930e72019-03-01 19:31:1118994 MockRead data_reads[] = {
18995 MockRead("HTTP/1.0 200 OK\r\n"),
18996 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18997 MockRead("hello world"),
18998 MockRead(ASYNC, OK),
18999 };
Lily Chenfec60d92019-01-24 01:16:4219000
19001 StaticSocketDataProvider reads(data_reads, data_writes);
19002 session_deps_.socket_factory->AddSocketDataProvider(&reads);
19003
19004 SSLSocketDataProvider ssl(ASYNC, OK);
19005 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19006
19007 // Log start time
19008 base::TimeTicks start_time = base::TimeTicks::Now();
19009
19010 TestCompletionCallback callback;
19011 auto session = CreateSession(&session_deps_);
19012 auto trans =
19013 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19014 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19015 EXPECT_THAT(callback.GetResult(rv), IsOk());
19016
19017 const HttpResponseInfo* response = trans->GetResponseInfo();
19018 ASSERT_TRUE(response);
19019
19020 EXPECT_TRUE(response->headers);
19021 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19022
19023 std::string response_data;
19024 rv = ReadTransaction(trans.get(), &response_data);
19025 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
19026
19027 trans.reset();
19028
19029 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19030
19031 CheckReport(0 /* index */, 200 /* status_code */,
19032 ERR_CONTENT_LENGTH_MISMATCH);
19033 const NetworkErrorLoggingService::RequestDetails& error =
19034 network_error_logging_service()->errors()[0];
19035 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
19036}
19037
19038TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19039 CreateReportRestartWithAuth) {
19040 std::string extra_header_string = extra_headers_.ToString();
19041 static const base::TimeDelta kSleepDuration =
19042 base::TimeDelta::FromMilliseconds(10);
19043
19044 MockWrite data_writes1[] = {
19045 MockWrite("GET / HTTP/1.1\r\n"
19046 "Host: www.example.org\r\n"
19047 "Connection: keep-alive\r\n"),
19048 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19049 };
19050
19051 MockRead data_reads1[] = {
19052 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19053 // Give a couple authenticate options (only the middle one is actually
19054 // supported).
19055 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19056 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19057 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19058 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19059 // Large content-length -- won't matter, as connection will be reset.
19060 MockRead("Content-Length: 10000\r\n\r\n"),
19061 MockRead(SYNCHRONOUS, ERR_FAILED),
19062 };
19063
19064 // After calling trans->RestartWithAuth(), this is the request we should
19065 // be issuing -- the final header line contains the credentials.
19066 MockWrite data_writes2[] = {
19067 MockWrite("GET / HTTP/1.1\r\n"
19068 "Host: www.example.org\r\n"
19069 "Connection: keep-alive\r\n"
19070 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19071 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19072 };
19073
19074 // Lastly, the server responds with the actual content.
19075 MockRead data_reads2[] = {
19076 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19077 MockRead("hello world"),
19078 MockRead(SYNCHRONOUS, OK),
19079 };
19080
19081 StaticSocketDataProvider data1(data_reads1, data_writes1);
19082 StaticSocketDataProvider data2(data_reads2, data_writes2);
19083 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19084 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19085
19086 SSLSocketDataProvider ssl1(ASYNC, OK);
19087 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19088 SSLSocketDataProvider ssl2(ASYNC, OK);
19089 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19090
19091 base::TimeTicks start_time = base::TimeTicks::Now();
19092 base::TimeTicks restart_time;
19093
19094 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19095 auto trans =
19096 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19097
19098 TestCompletionCallback callback1;
19099
19100 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19101 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19102
19103 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19104
19105 TestCompletionCallback callback2;
19106
19107 // Wait 10 ms then restart with auth
19108 FastForwardBy(kSleepDuration);
19109 restart_time = base::TimeTicks::Now();
19110 rv =
19111 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19112 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19113
19114 std::string response_data;
19115 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19116 EXPECT_EQ("hello world", response_data);
19117
19118 trans.reset();
19119
19120 // One 401 report for the auth challenge, then a 200 report for the successful
19121 // retry. Note that we don't report the error draining the body, as the first
19122 // request already generated a report for the auth challenge.
19123 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19124
19125 // Check error report contents
19126 CheckReport(0 /* index */, 401 /* status_code */, OK);
19127 CheckReport(1 /* index */, 200 /* status_code */, OK);
19128
19129 const NetworkErrorLoggingService::RequestDetails& error1 =
19130 network_error_logging_service()->errors()[0];
19131 const NetworkErrorLoggingService::RequestDetails& error2 =
19132 network_error_logging_service()->errors()[1];
19133
19134 // Sanity-check elapsed time values
19135 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19136 // Check that the start time is refreshed when restarting with auth.
19137 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19138}
19139
19140// Same as above, except draining the body before restarting fails
19141// asynchronously.
19142TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19143 CreateReportRestartWithAuthAsync) {
19144 std::string extra_header_string = extra_headers_.ToString();
19145 static const base::TimeDelta kSleepDuration =
19146 base::TimeDelta::FromMilliseconds(10);
19147
19148 MockWrite data_writes1[] = {
19149 MockWrite("GET / HTTP/1.1\r\n"
19150 "Host: www.example.org\r\n"
19151 "Connection: keep-alive\r\n"),
19152 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19153 };
19154
19155 MockRead data_reads1[] = {
19156 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
19157 // Give a couple authenticate options (only the middle one is actually
19158 // supported).
19159 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
19160 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19161 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
19162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19163 // Large content-length -- won't matter, as connection will be reset.
19164 MockRead("Content-Length: 10000\r\n\r\n"),
19165 MockRead(ASYNC, ERR_FAILED),
19166 };
19167
19168 // After calling trans->RestartWithAuth(), this is the request we should
19169 // be issuing -- the final header line contains the credentials.
19170 MockWrite data_writes2[] = {
19171 MockWrite("GET / HTTP/1.1\r\n"
19172 "Host: www.example.org\r\n"
19173 "Connection: keep-alive\r\n"
19174 "Authorization: Basic Zm9vOmJhcg==\r\n"),
19175 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19176 };
19177
19178 // Lastly, the server responds with the actual content.
19179 MockRead data_reads2[] = {
19180 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19181 MockRead("hello world"),
19182 MockRead(SYNCHRONOUS, OK),
19183 };
19184
19185 StaticSocketDataProvider data1(data_reads1, data_writes1);
19186 StaticSocketDataProvider data2(data_reads2, data_writes2);
19187 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19188 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19189
19190 SSLSocketDataProvider ssl1(ASYNC, OK);
19191 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19192 SSLSocketDataProvider ssl2(ASYNC, OK);
19193 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19194
19195 base::TimeTicks start_time = base::TimeTicks::Now();
19196 base::TimeTicks restart_time;
19197
19198 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19199 auto trans =
19200 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19201
19202 TestCompletionCallback callback1;
19203
19204 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19205 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19206
19207 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19208
19209 TestCompletionCallback callback2;
19210
19211 // Wait 10 ms then restart with auth
19212 FastForwardBy(kSleepDuration);
19213 restart_time = base::TimeTicks::Now();
19214 rv =
19215 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19216 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19217
19218 std::string response_data;
19219 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19220 EXPECT_EQ("hello world", response_data);
19221
19222 trans.reset();
19223
19224 // One 401 report for the auth challenge, then a 200 report for the successful
19225 // retry. Note that we don't report the error draining the body, as the first
19226 // request already generated a report for the auth challenge.
19227 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19228
19229 // Check error report contents
19230 CheckReport(0 /* index */, 401 /* status_code */, OK);
19231 CheckReport(1 /* index */, 200 /* status_code */, OK);
19232
19233 const NetworkErrorLoggingService::RequestDetails& error1 =
19234 network_error_logging_service()->errors()[0];
19235 const NetworkErrorLoggingService::RequestDetails& error2 =
19236 network_error_logging_service()->errors()[1];
19237
19238 // Sanity-check elapsed time values
19239 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19240 // Check that the start time is refreshed when restarting with auth.
19241 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19242}
19243
19244TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19245 CreateReportRetryKeepAliveConnectionReset) {
19246 std::string extra_header_string = extra_headers_.ToString();
19247 MockWrite data_writes1[] = {
19248 MockWrite("GET / HTTP/1.1\r\n"
19249 "Host: www.example.org\r\n"
19250 "Connection: keep-alive\r\n"),
19251 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19252 MockWrite("GET / HTTP/1.1\r\n"
19253 "Host: www.example.org\r\n"
19254 "Connection: keep-alive\r\n"),
19255 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19256 };
19257
19258 MockRead data_reads1[] = {
19259 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19260 MockRead("hello"),
19261 // Connection is reset
19262 MockRead(ASYNC, ERR_CONNECTION_RESET),
19263 };
19264
19265 // Successful retry
19266 MockRead data_reads2[] = {
19267 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19268 MockRead("world"),
19269 MockRead(ASYNC, OK),
19270 };
19271
19272 StaticSocketDataProvider data1(data_reads1, data_writes1);
19273 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19274 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19275 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19276
19277 SSLSocketDataProvider ssl1(ASYNC, OK);
19278 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19279 SSLSocketDataProvider ssl2(ASYNC, OK);
19280 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19281
19282 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19283 auto trans1 =
19284 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19285
19286 TestCompletionCallback callback1;
19287
19288 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19289 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19290
19291 std::string response_data;
19292 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19293 EXPECT_EQ("hello", response_data);
19294
19295 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19296
19297 auto trans2 =
19298 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19299
19300 TestCompletionCallback callback2;
19301
19302 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19303 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19304
19305 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19306 EXPECT_EQ("world", response_data);
19307
19308 trans1.reset();
19309 trans2.reset();
19310
19311 // One OK report from first request, then a ERR_CONNECTION_RESET report from
19312 // the second request, then an OK report from the successful retry.
19313 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19314
19315 // Check error report contents
19316 CheckReport(0 /* index */, 200 /* status_code */, OK);
19317 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
19318 CheckReport(2 /* index */, 200 /* status_code */, OK);
19319}
19320
19321TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19322 CreateReportRetryKeepAlive408) {
19323 std::string extra_header_string = extra_headers_.ToString();
19324 MockWrite data_writes1[] = {
19325 MockWrite("GET / HTTP/1.1\r\n"
19326 "Host: www.example.org\r\n"
19327 "Connection: keep-alive\r\n"),
19328 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19329 MockWrite("GET / HTTP/1.1\r\n"
19330 "Host: www.example.org\r\n"
19331 "Connection: keep-alive\r\n"),
19332 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19333 };
19334
19335 MockRead data_reads1[] = {
19336 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19337 MockRead("hello"),
19338 // 408 Request Timeout
19339 MockRead(SYNCHRONOUS,
19340 "HTTP/1.1 408 Request Timeout\r\n"
19341 "Connection: Keep-Alive\r\n"
19342 "Content-Length: 6\r\n\r\n"
19343 "Pickle"),
19344 };
19345
19346 // Successful retry
19347 MockRead data_reads2[] = {
19348 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19349 MockRead("world"),
19350 MockRead(ASYNC, OK),
19351 };
19352
19353 StaticSocketDataProvider data1(data_reads1, data_writes1);
19354 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19355 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19356 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19357
19358 SSLSocketDataProvider ssl1(ASYNC, OK);
19359 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19360 SSLSocketDataProvider ssl2(ASYNC, OK);
19361 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19362
19363 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19364 auto trans1 =
19365 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19366
19367 TestCompletionCallback callback1;
19368
19369 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19370 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19371
19372 std::string response_data;
19373 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19374 EXPECT_EQ("hello", response_data);
19375
19376 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19377
19378 auto trans2 =
19379 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19380
19381 TestCompletionCallback callback2;
19382
19383 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19384 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19385
19386 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19387 EXPECT_EQ("world", response_data);
19388
19389 trans1.reset();
19390 trans2.reset();
19391
19392 // One 200 report from first request, then a 408 report from
19393 // the second request, then a 200 report from the successful retry.
19394 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19395
19396 // Check error report contents
19397 CheckReport(0 /* index */, 200 /* status_code */, OK);
19398 CheckReport(1 /* index */, 408 /* status_code */, OK);
19399 CheckReport(2 /* index */, 200 /* status_code */, OK);
19400}
19401
19402TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19403 CreateReportRetry421WithoutConnectionPooling) {
19404 // Two hosts resolve to the same IP address.
19405 const std::string ip_addr = "1.2.3.4";
19406 IPAddress ip;
19407 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
19408 IPEndPoint peer_addr = IPEndPoint(ip, 443);
19409
19410 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19411 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
19412 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
19413
19414 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19415
19416 // Two requests on the first connection.
19417 spdy::SpdySerializedFrame req1(
19418 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19419 spdy_util_.UpdateWithStreamDestruction(1);
19420 spdy::SpdySerializedFrame req2(
19421 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
19422 spdy::SpdySerializedFrame rst(
19423 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
19424 MockWrite writes1[] = {
19425 CreateMockWrite(req1, 0),
19426 CreateMockWrite(req2, 3),
19427 CreateMockWrite(rst, 6),
19428 };
19429
19430 // The first one succeeds, the second gets error 421 Misdirected Request.
19431 spdy::SpdySerializedFrame resp1(
19432 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19433 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
19434 spdy::SpdyHeaderBlock response_headers;
19435 response_headers[spdy::kHttp2StatusHeader] = "421";
19436 spdy::SpdySerializedFrame resp2(
19437 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
19438 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
19439 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
19440
19441 MockConnect connect1(ASYNC, OK, peer_addr);
19442 SequencedSocketData data1(connect1, reads1, writes1);
19443 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19444
19445 AddSSLSocketData();
19446
19447 // Retry the second request on a second connection.
19448 SpdyTestUtil spdy_util2;
19449 spdy::SpdySerializedFrame req3(
19450 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
19451 MockWrite writes2[] = {
19452 CreateMockWrite(req3, 0),
19453 };
19454
19455 spdy::SpdySerializedFrame resp3(
19456 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
19457 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
19458 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
19459 MockRead(ASYNC, 0, 3)};
19460
19461 MockConnect connect2(ASYNC, OK, peer_addr);
19462 SequencedSocketData data2(connect2, reads2, writes2);
19463 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19464
19465 AddSSLSocketData();
19466
19467 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3319468 int rv = session_deps_.host_resolver->LoadIntoCache(
19469 HostPortPair("mail.example.com", 443), base::nullopt);
19470 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4219471
19472 HttpRequestInfo request1;
19473 request1.method = "GET";
19474 request1.url = GURL("https://www.example.org/");
19475 request1.load_flags = 0;
19476 request1.traffic_annotation =
19477 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19478 auto trans1 =
19479 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19480
Eric Orthf4db66a2019-02-19 21:35:3319481 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219482 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
19483 EXPECT_THAT(callback.GetResult(rv), IsOk());
19484
19485 const HttpResponseInfo* response = trans1->GetResponseInfo();
19486 ASSERT_TRUE(response);
19487 ASSERT_TRUE(response->headers);
19488 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19489 EXPECT_TRUE(response->was_fetched_via_spdy);
19490 EXPECT_TRUE(response->was_alpn_negotiated);
19491 std::string response_data;
19492 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19493 EXPECT_EQ("hello!", response_data);
19494
19495 trans1.reset();
19496
19497 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19498
19499 HttpRequestInfo request2;
19500 request2.method = "GET";
19501 request2.url = GURL("https://mail.example.org/");
19502 request2.load_flags = 0;
19503 request2.traffic_annotation =
19504 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19505 auto trans2 =
19506 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19507
19508 BoundTestNetLog log;
19509 rv = trans2->Start(&request2, callback.callback(), log.bound());
19510 EXPECT_THAT(callback.GetResult(rv), IsOk());
19511
19512 response = trans2->GetResponseInfo();
19513 ASSERT_TRUE(response);
19514 ASSERT_TRUE(response->headers);
19515 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19516 EXPECT_TRUE(response->was_fetched_via_spdy);
19517 EXPECT_TRUE(response->was_alpn_negotiated);
19518 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19519 EXPECT_EQ("hello!", response_data);
19520
19521 trans2.reset();
19522
19523 // One 200 report from the first request, then a 421 report from the
19524 // second request, then a 200 report from the successful retry.
19525 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19526
19527 // Check error report contents
19528 const NetworkErrorLoggingService::RequestDetails& error1 =
19529 network_error_logging_service()->errors()[0];
19530 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
19531 EXPECT_TRUE(error1.referrer.is_empty());
19532 EXPECT_EQ("", error1.user_agent);
19533 EXPECT_EQ(ip, error1.server_ip);
19534 EXPECT_EQ("h2", error1.protocol);
19535 EXPECT_EQ("GET", error1.method);
19536 EXPECT_EQ(200, error1.status_code);
19537 EXPECT_EQ(OK, error1.type);
19538 EXPECT_EQ(0, error1.reporting_upload_depth);
19539
19540 const NetworkErrorLoggingService::RequestDetails& error2 =
19541 network_error_logging_service()->errors()[1];
19542 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
19543 EXPECT_TRUE(error2.referrer.is_empty());
19544 EXPECT_EQ("", error2.user_agent);
19545 EXPECT_EQ(ip, error2.server_ip);
19546 EXPECT_EQ("h2", error2.protocol);
19547 EXPECT_EQ("GET", error2.method);
19548 EXPECT_EQ(421, error2.status_code);
19549 EXPECT_EQ(OK, error2.type);
19550 EXPECT_EQ(0, error2.reporting_upload_depth);
19551
19552 const NetworkErrorLoggingService::RequestDetails& error3 =
19553 network_error_logging_service()->errors()[2];
19554 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
19555 EXPECT_TRUE(error3.referrer.is_empty());
19556 EXPECT_EQ("", error3.user_agent);
19557 EXPECT_EQ(ip, error3.server_ip);
19558 EXPECT_EQ("h2", error3.protocol);
19559 EXPECT_EQ("GET", error3.method);
19560 EXPECT_EQ(200, error3.status_code);
19561 EXPECT_EQ(OK, error3.type);
19562 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3619563}
19564
Lily Chend3930e72019-03-01 19:31:1119565TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19566 CreateReportCancelAfterStart) {
19567 StaticSocketDataProvider data;
19568 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
19569 session_deps_.socket_factory->AddSocketDataProvider(&data);
19570
19571 TestCompletionCallback callback;
19572 auto session = CreateSession(&session_deps_);
19573 auto trans =
19574 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19575 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19576 EXPECT_EQ(rv, ERR_IO_PENDING);
19577
19578 // Cancel after start.
19579 trans.reset();
19580
19581 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19582 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
19583 IPAddress() /* server_ip */);
19584}
19585
19586TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19587 CreateReportCancelBeforeReadingBody) {
19588 std::string extra_header_string = extra_headers_.ToString();
19589 MockWrite data_writes[] = {
19590 MockWrite("GET / HTTP/1.1\r\n"
19591 "Host: www.example.org\r\n"
19592 "Connection: keep-alive\r\n"),
19593 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19594 };
19595 MockRead data_reads[] = {
19596 MockRead("HTTP/1.0 200 OK\r\n"),
19597 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
19598 };
19599
19600 StaticSocketDataProvider data(data_reads, data_writes);
19601 session_deps_.socket_factory->AddSocketDataProvider(&data);
19602
19603 SSLSocketDataProvider ssl(ASYNC, OK);
19604 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19605
19606 TestCompletionCallback callback;
19607 auto session = CreateSession(&session_deps_);
19608 auto trans =
19609 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19610 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19611 EXPECT_THAT(callback.GetResult(rv), IsOk());
19612
19613 const HttpResponseInfo* response = trans->GetResponseInfo();
19614 ASSERT_TRUE(response);
19615
19616 EXPECT_TRUE(response->headers);
19617 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19618
19619 // Cancel before reading the body.
19620 trans.reset();
19621
19622 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19623 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
19624}
19625
Lily Chen00196ab62018-12-04 19:52:2919626TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
19627 base::HistogramTester histograms;
19628 RequestPolicy();
19629 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19630 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19631
19632 // Make HTTP request
19633 std::string extra_header_string = extra_headers_.ToString();
19634 MockRead data_reads[] = {
19635 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19636 MockRead("hello world"),
19637 MockRead(SYNCHRONOUS, OK),
19638 };
19639 MockWrite data_writes[] = {
19640 MockWrite("GET / HTTP/1.1\r\n"
19641 "Host: www.example.org\r\n"
19642 "Connection: keep-alive\r\n"),
19643 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19644 };
19645
Lily Chend3930e72019-03-01 19:31:1119646 StaticSocketDataProvider data(data_reads, data_writes);
19647 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2919648
Lily Chenfec60d92019-01-24 01:16:4219649 // Insecure url
19650 url_ = "http://www.example.org/";
19651 request_.url = GURL(url_);
19652
Lily Chen00196ab62018-12-04 19:52:2919653 TestCompletionCallback callback;
19654 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4219655 auto trans =
19656 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19657 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19658 EXPECT_THAT(callback.GetResult(rv), IsOk());
19659
19660 std::string response_data;
19661 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19662 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2919663
19664 // Insecure request does not generate a report
19665 histograms.ExpectBucketCount(
19666 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519667 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919668
19669 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19670}
19671
19672TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19673 DontCreateReportHttpError) {
19674 base::HistogramTester histograms;
19675 RequestPolicy();
19676 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19677 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19678
19679 // Make HTTP request that fails
19680 MockRead data_reads[] = {
19681 MockRead("hello world"),
19682 MockRead(SYNCHRONOUS, OK),
19683 };
19684
19685 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19686 session_deps_.socket_factory->AddSocketDataProvider(&data);
19687
Lily Chenfec60d92019-01-24 01:16:4219688 url_ = "http://www.originwithoutpolicy.com:2000/";
19689 request_.url = GURL(url_);
19690
Lily Chen00196ab62018-12-04 19:52:2919691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19692
Lily Chen00196ab62018-12-04 19:52:2919693 auto trans =
19694 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2919695 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219696 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2919697 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
19698
19699 // Insecure request does not generate a report, regardless of existence of a
19700 // policy for the origin.
19701 histograms.ExpectBucketCount(
19702 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519703 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919704
19705 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19706}
19707
Lily Chen90ae93cc2019-02-14 01:15:3919708// Don't report on proxy auth challenges, don't report if connecting through a
19709// proxy.
19710TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
19711 HttpRequestInfo request;
19712 request.method = "GET";
19713 request.url = GURL("https://www.example.org/");
19714 request.traffic_annotation =
19715 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19716
19717 // Configure against proxy server "myproxy:70".
19718 session_deps_.proxy_resolution_service =
19719 ProxyResolutionService::CreateFixedFromPacResult(
19720 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19721 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19722
19723 // Since we have proxy, should try to establish tunnel.
19724 MockWrite data_writes1[] = {
19725 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19726 "Host: www.example.org:443\r\n"
19727 "Proxy-Connection: keep-alive\r\n\r\n"),
19728 };
19729
19730 // The proxy responds to the connect with a 407, using a non-persistent
19731 // connection.
19732 MockRead data_reads1[] = {
19733 // No credentials.
19734 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
19735 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19736 MockRead("Proxy-Connection: close\r\n\r\n"),
19737 };
19738
19739 MockWrite data_writes2[] = {
19740 // After calling trans->RestartWithAuth(), this is the request we should
19741 // be issuing -- the final header line contains the credentials.
19742 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19743 "Host: www.example.org:443\r\n"
19744 "Proxy-Connection: keep-alive\r\n"
19745 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
19746
19747 MockWrite("GET / HTTP/1.1\r\n"
19748 "Host: www.example.org\r\n"
19749 "Connection: keep-alive\r\n\r\n"),
19750 };
19751
19752 MockRead data_reads2[] = {
19753 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19754
19755 MockRead("HTTP/1.1 200 OK\r\n"),
19756 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19757 MockRead("Content-Length: 5\r\n\r\n"),
19758 MockRead(SYNCHRONOUS, "hello"),
19759 };
19760
19761 StaticSocketDataProvider data1(data_reads1, data_writes1);
19762 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19763 StaticSocketDataProvider data2(data_reads2, data_writes2);
19764 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19765 SSLSocketDataProvider ssl(ASYNC, OK);
19766 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19767
19768 TestCompletionCallback callback1;
19769
19770 auto trans =
19771 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19772
19773 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
19774 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19775
19776 const HttpResponseInfo* response = trans->GetResponseInfo();
19777 EXPECT_EQ(407, response->headers->response_code());
19778
19779 std::string response_data;
19780 rv = ReadTransaction(trans.get(), &response_data);
19781 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
19782
19783 // No NEL report is generated for the 407.
19784 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19785
19786 TestCompletionCallback callback2;
19787
19788 rv =
19789 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19790 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19791
19792 response = trans->GetResponseInfo();
19793 EXPECT_EQ(200, response->headers->response_code());
19794
19795 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19796 EXPECT_EQ("hello", response_data);
19797
19798 trans.reset();
19799
19800 // No NEL report is generated because we are behind a proxy.
19801 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19802}
19803
Douglas Creageref5eecdc2018-11-09 20:50:3619804TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19805 ReportContainsUploadDepth) {
19806 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4219807 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3619808 RequestPolicy();
19809 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219810 const NetworkErrorLoggingService::RequestDetails& error =
19811 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3619812 EXPECT_EQ(7, error.reporting_upload_depth);
19813}
19814
Lily Chenfec60d92019-01-24 01:16:4219815TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
19816 std::string extra_header_string = extra_headers_.ToString();
19817 static const base::TimeDelta kSleepDuration =
19818 base::TimeDelta::FromMilliseconds(10);
19819
19820 std::vector<MockWrite> data_writes = {
19821 MockWrite(ASYNC, 0,
19822 "GET / HTTP/1.1\r\n"
19823 "Host: www.example.org\r\n"
19824 "Connection: keep-alive\r\n"),
19825 MockWrite(ASYNC, 1, extra_header_string.data()),
19826 };
19827
19828 std::vector<MockRead> data_reads = {
19829 // Write one byte of the status line, followed by a pause.
19830 MockRead(ASYNC, 2, "H"),
19831 MockRead(ASYNC, ERR_IO_PENDING, 3),
19832 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
19833 MockRead(ASYNC, 5, "hello world"),
19834 MockRead(SYNCHRONOUS, OK, 6),
19835 };
19836
19837 SequencedSocketData data(data_reads, data_writes);
19838 session_deps_.socket_factory->AddSocketDataProvider(&data);
19839
19840 SSLSocketDataProvider ssl(ASYNC, OK);
19841 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19842
19843 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19844
19845 auto trans =
19846 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19847
19848 TestCompletionCallback callback;
19849
19850 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19851 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19852
19853 data.RunUntilPaused();
19854 ASSERT_TRUE(data.IsPaused());
19855 FastForwardBy(kSleepDuration);
19856 data.Resume();
19857
19858 EXPECT_THAT(callback.GetResult(rv), IsOk());
19859
19860 std::string response_data;
19861 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19862 EXPECT_EQ("hello world", response_data);
19863
19864 trans.reset();
19865
Douglas Creageref5eecdc2018-11-09 20:50:3619866 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219867
19868 CheckReport(0 /* index */, 200 /* status_code */, OK);
19869
19870 const NetworkErrorLoggingService::RequestDetails& error =
19871 network_error_logging_service()->errors()[0];
19872
19873 // Sanity-check elapsed time in error report
19874 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3619875}
Lily Chenfec60d92019-01-24 01:16:4219876
Douglas Creager3cb042052018-11-06 23:08:5219877#endif // BUILDFLAG(ENABLE_REPORTING)
19878
Batalov Vladislava4e97a502019-04-11 15:35:2319879TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
19880 HttpRequestInfo request;
19881 request.method = "GET";
19882 request.url = GURL("http://example.org/");
19883
19884 request.load_flags = LOAD_ONLY_FROM_CACHE;
19885
19886 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19887 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19888 TestCompletionCallback callback1;
19889 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
19890
19891 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
19892}
19893
Steven Valdez1c1859172019-04-10 15:33:2819894TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
19895 HttpRequestInfo request;
19896 request.method = "GET";
19897 request.url = GURL("https://www.example.org/");
19898 request.traffic_annotation =
19899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19900
19901 MockWrite data_writes[] = {
19902 MockWrite("GET / HTTP/1.1\r\n"
19903 "Host: www.example.org\r\n"
19904 "Connection: keep-alive\r\n\r\n"),
19905 };
19906
Steven Valdez1c1859172019-04-10 15:33:2819907 MockRead data_reads[] = {
19908 MockRead("HTTP/1.1 200 OK\r\n"),
19909 MockRead("Content-Length: 1\r\n\r\n"),
19910 MockRead(SYNCHRONOUS, "1"),
19911 };
19912
19913 StaticSocketDataProvider data(data_reads, data_writes);
19914 session_deps_.socket_factory->AddSocketDataProvider(&data);
19915 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19916 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19917 session_deps_.enable_early_data = true;
19918 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19919
19920 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19921
19922 TestCompletionCallback callback;
19923 auto trans =
19924 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19925
19926 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19927 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19928
19929 rv = callback.WaitForResult();
19930 EXPECT_THAT(rv, IsOk());
19931
19932 const HttpResponseInfo* response = trans->GetResponseInfo();
19933 ASSERT_TRUE(response);
19934 ASSERT_TRUE(response->headers);
19935 EXPECT_EQ(200, response->headers->response_code());
19936 EXPECT_EQ(1, response->headers->GetContentLength());
19937
19938 // Check that ConfirmHandshake wasn't called.
19939 ASSERT_FALSE(ssl.ConfirmDataConsumed());
19940 ASSERT_TRUE(ssl.WriteBeforeConfirm());
19941
19942 trans.reset();
19943
19944 session->CloseAllConnections();
19945}
19946
19947TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
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(SYNCHRONOUS, 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, ZeroRTTSyncConfirmAsyncWrite) {
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(SYNCHRONOUS, 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
20055TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
20056 HttpRequestInfo request;
20057 request.method = "POST";
20058 request.url = GURL("https://www.example.org/");
20059 request.traffic_annotation =
20060 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20061
20062 MockWrite data_writes[] = {
20063 MockWrite(SYNCHRONOUS,
20064 "POST / HTTP/1.1\r\n"
20065 "Host: www.example.org\r\n"
20066 "Connection: keep-alive\r\n"
20067 "Content-Length: 0\r\n\r\n"),
20068 };
20069
Steven Valdez1c1859172019-04-10 15:33:2820070 MockRead data_reads[] = {
20071 MockRead("HTTP/1.1 200 OK\r\n"),
20072 MockRead("Content-Length: 1\r\n\r\n"),
20073 MockRead(SYNCHRONOUS, "1"),
20074 };
20075
20076 StaticSocketDataProvider data(data_reads, data_writes);
20077 session_deps_.socket_factory->AddSocketDataProvider(&data);
20078 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20079 ssl.confirm = MockConfirm(ASYNC, OK);
20080 session_deps_.enable_early_data = true;
20081 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20082
20083 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20084
20085 TestCompletionCallback callback;
20086 auto trans =
20087 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20088
20089 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20090 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20091
20092 rv = callback.WaitForResult();
20093 EXPECT_THAT(rv, IsOk());
20094
20095 const HttpResponseInfo* response = trans->GetResponseInfo();
20096 ASSERT_TRUE(response);
20097 ASSERT_TRUE(response->headers);
20098 EXPECT_EQ(200, response->headers->response_code());
20099 EXPECT_EQ(1, response->headers->GetContentLength());
20100
20101 // Check that the Write didn't get called before ConfirmHandshake completed.
20102 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20103
20104 trans.reset();
20105
20106 session->CloseAllConnections();
20107}
20108
20109TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
20110 HttpRequestInfo request;
20111 request.method = "POST";
20112 request.url = GURL("https://www.example.org/");
20113 request.traffic_annotation =
20114 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20115
20116 MockWrite data_writes[] = {
20117 MockWrite(ASYNC,
20118 "POST / HTTP/1.1\r\n"
20119 "Host: www.example.org\r\n"
20120 "Connection: keep-alive\r\n"
20121 "Content-Length: 0\r\n\r\n"),
20122 };
20123
Steven Valdez1c1859172019-04-10 15:33:2820124 MockRead data_reads[] = {
20125 MockRead("HTTP/1.1 200 OK\r\n"),
20126 MockRead("Content-Length: 1\r\n\r\n"),
20127 MockRead(SYNCHRONOUS, "1"),
20128 };
20129
20130 StaticSocketDataProvider data(data_reads, data_writes);
20131 session_deps_.socket_factory->AddSocketDataProvider(&data);
20132 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20133 ssl.confirm = MockConfirm(ASYNC, OK);
20134 session_deps_.enable_early_data = true;
20135 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20136
20137 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20138
20139 TestCompletionCallback callback;
20140 auto trans =
20141 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20142
20143 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20144 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20145
20146 rv = callback.WaitForResult();
20147 EXPECT_THAT(rv, IsOk());
20148
20149 const HttpResponseInfo* response = trans->GetResponseInfo();
20150 ASSERT_TRUE(response);
20151 ASSERT_TRUE(response->headers);
20152 EXPECT_EQ(200, response->headers->response_code());
20153 EXPECT_EQ(1, response->headers->GetContentLength());
20154
20155 // Check that the Write didn't get called before ConfirmHandshake completed.
20156 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20157
20158 trans.reset();
20159
20160 session->CloseAllConnections();
20161}
20162
David Benjaminfb976932019-05-15 13:39:1520163// 0-RTT rejects are handled at HttpNetworkTransaction.
20164TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
20165 enum class RejectType {
20166 kRead,
20167 kWrite,
20168 kConfirm,
20169 };
20170
20171 for (RejectType type :
20172 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
20173 SCOPED_TRACE(static_cast<int>(type));
20174 for (Error reject_error :
20175 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
20176 SCOPED_TRACE(reject_error);
20177 session_deps_.socket_factory =
20178 std::make_unique<MockClientSocketFactory>();
20179
20180 HttpRequestInfo request;
20181 request.method = type == RejectType::kConfirm ? "POST" : "GET";
20182 request.url = GURL("https://www.example.org/");
20183 request.traffic_annotation =
20184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20185
20186 // The first request fails.
20187 std::vector<MockWrite> data1_writes;
20188 std::vector<MockRead> data1_reads;
20189 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
20190 switch (type) {
20191 case RejectType::kRead:
20192 data1_writes.emplace_back(
20193 "GET / HTTP/1.1\r\n"
20194 "Host: www.example.org\r\n"
20195 "Connection: keep-alive\r\n\r\n");
20196 data1_reads.emplace_back(ASYNC, reject_error);
20197 // Cause ConfirmHandshake to hang (it should not be called).
20198 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20199 break;
20200 case RejectType::kWrite:
20201 data1_writes.emplace_back(ASYNC, reject_error);
20202 // Cause ConfirmHandshake to hang (it should not be called).
20203 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20204 break;
20205 case RejectType::kConfirm:
20206 // The request never gets far enough to read or write.
20207 ssl1.confirm = MockConfirm(ASYNC, reject_error);
20208 break;
20209 }
20210
20211 StaticSocketDataProvider data1(data1_reads, data1_writes);
20212 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20213 session_deps_.enable_early_data = true;
20214 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20215
20216 // The retry succeeds.
20217 //
20218 // TODO(https://crbug.com/950705): If |reject_error| is
20219 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
20220 MockWrite data2_writes[] = {
20221 request.method == "POST"
20222 ? MockWrite("POST / HTTP/1.1\r\n"
20223 "Host: www.example.org\r\n"
20224 "Connection: keep-alive\r\n"
20225 "Content-Length: 0\r\n\r\n")
20226 : MockWrite("GET / HTTP/1.1\r\n"
20227 "Host: www.example.org\r\n"
20228 "Connection: keep-alive\r\n\r\n"),
20229 };
20230
20231 MockRead data2_reads[] = {
20232 MockRead("HTTP/1.1 200 OK\r\n"),
20233 MockRead("Content-Length: 1\r\n\r\n"),
20234 MockRead(SYNCHRONOUS, "1"),
20235 };
20236
20237 StaticSocketDataProvider data2(data2_reads, data2_writes);
20238 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20239 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
20240 ssl2.confirm = MockConfirm(ASYNC, OK);
20241 session_deps_.enable_early_data = true;
20242 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20243
20244 std::unique_ptr<HttpNetworkSession> session(
20245 CreateSession(&session_deps_));
20246
20247 TestCompletionCallback callback;
20248 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20249 session.get());
20250
20251 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20252 NetLogWithSource())),
20253 IsOk());
20254
20255 const HttpResponseInfo* response = trans->GetResponseInfo();
20256 ASSERT_TRUE(response);
20257 ASSERT_TRUE(response->headers);
20258 EXPECT_EQ(200, response->headers->response_code());
20259 EXPECT_EQ(1, response->headers->GetContentLength());
20260 }
20261 }
20262}
20263
Steven Valdez1c1859172019-04-10 15:33:2820264TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
20265 HttpRequestInfo request;
20266 request.method = "POST";
20267 request.url = GURL("https://www.example.org/");
20268 request.traffic_annotation =
20269 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20270
20271 MockWrite data_writes[] = {
20272 MockWrite("POST / HTTP/1.1\r\n"
20273 "Host: www.example.org\r\n"
20274 "Connection: keep-alive\r\n"
20275 "Content-Length: 0\r\n\r\n"),
20276 };
20277
Steven Valdez1c1859172019-04-10 15:33:2820278 MockRead data_reads[] = {
20279 MockRead("HTTP/1.1 200 OK\r\n"),
20280 MockRead("Content-Length: 1\r\n\r\n"),
20281 MockRead(SYNCHRONOUS, "1"),
20282 };
20283
20284 StaticSocketDataProvider data(data_reads, data_writes);
20285 session_deps_.socket_factory->AddSocketDataProvider(&data);
20286 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20287 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
20288 session_deps_.enable_early_data = true;
20289 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20290
20291 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20292
20293 TestCompletionCallback callback;
20294 auto trans =
20295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20296
20297 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20298 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20299
20300 rv = callback.WaitForResult();
20301 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20302
20303 // Check that the Write didn't get called before ConfirmHandshake completed.
20304 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20305
20306 trans.reset();
20307
20308 session->CloseAllConnections();
20309}
20310
20311TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
20312 HttpRequestInfo request;
20313 request.method = "POST";
20314 request.url = GURL("https://www.example.org/");
20315 request.traffic_annotation =
20316 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20317
20318 MockWrite data_writes[] = {
20319 MockWrite("POST / HTTP/1.1\r\n"
20320 "Host: www.example.org\r\n"
20321 "Connection: keep-alive\r\n"
20322 "Content-Length: 0\r\n\r\n"),
20323 };
20324
Steven Valdez1c1859172019-04-10 15:33:2820325 MockRead data_reads[] = {
20326 MockRead("HTTP/1.1 200 OK\r\n"),
20327 MockRead("Content-Length: 1\r\n\r\n"),
20328 MockRead(SYNCHRONOUS, "1"),
20329 };
20330
20331 StaticSocketDataProvider data(data_reads, data_writes);
20332 session_deps_.socket_factory->AddSocketDataProvider(&data);
20333 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20334 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
20335 session_deps_.enable_early_data = true;
20336 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20337
20338 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20339
20340 TestCompletionCallback callback;
20341 auto trans =
20342 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20343
20344 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20345 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20346
20347 rv = callback.WaitForResult();
20348 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20349
20350 // Check that the Write didn't get called before ConfirmHandshake completed.
20351 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20352
20353 trans.reset();
20354
20355 session->CloseAllConnections();
20356}
20357
David Benjamin2eb827f2019-04-29 18:31:0420358// Test the proxy and origin server each requesting both TLS client certificates
20359// and HTTP auth. This is a regression test for https://crbug.com/946406.
20360TEST_F(HttpNetworkTransactionTest, AuthEverything) {
20361 // Note these hosts must match the CheckBasic*Auth() functions.
20362 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20363 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20364
20365 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20366 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20367
20368 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20369 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20370 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20371 ASSERT_TRUE(identity_proxy);
20372
20373 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20374 cert_request_info_origin->host_and_port =
20375 HostPortPair("www.example.org", 443);
20376
20377 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20378 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20379 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20380 ASSERT_TRUE(identity_origin);
20381
20382 HttpRequestInfo request;
20383 request.method = "GET";
20384 request.url = GURL("https://www.example.org/");
20385 request.traffic_annotation =
20386 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20387
David Benjamin7ebab032019-04-30 21:51:3020388 // First, the client connects to the proxy, which requests a client
20389 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420390 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20391 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20392 ssl_proxy1.expected_send_client_cert = false;
David Benjamin2eb827f2019-04-29 18:31:0420393 StaticSocketDataProvider data1;
20394 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020395 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420396
David Benjamin7ebab032019-04-30 21:51:3020397 // The client responds with a certificate on a new connection. The handshake
20398 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420399 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20400 ssl_proxy2.expected_send_client_cert = true;
20401 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020402 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420403 std::vector<MockWrite> mock_writes2;
20404 std::vector<MockRead> mock_reads2;
20405 mock_writes2.emplace_back(
20406 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20407 "Host: www.example.org:443\r\n"
20408 "Proxy-Connection: keep-alive\r\n\r\n");
20409 mock_reads2.emplace_back(
20410 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20411 "Content-Length: 0\r\n"
20412 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020413 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0420414 mock_writes2.emplace_back(
20415 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20416 "Host: www.example.org:443\r\n"
20417 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020418 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420419 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20420 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20421 // The origin requests client certificates.
20422 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20423 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin2eb827f2019-04-29 18:31:0420424 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20425 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020426 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20427 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0420428
David Benjamin7ebab032019-04-30 21:51:3020429 // The client responds to the origin client certificate request on a new
20430 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420431 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20432 ssl_proxy3.expected_send_client_cert = true;
20433 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin2eb827f2019-04-29 18:31:0420434 std::vector<MockWrite> mock_writes3;
20435 std::vector<MockRead> mock_reads3;
20436 mock_writes3.emplace_back(
20437 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20438 "Host: www.example.org:443\r\n"
20439 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020440 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420441 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20442 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20443 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
20444 ssl_origin3.expected_send_client_cert = true;
20445 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020446 // The client sends the origin HTTP request, which results in another HTTP
20447 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0420448 mock_writes3.emplace_back(
20449 "GET / HTTP/1.1\r\n"
20450 "Host: www.example.org\r\n"
20451 "Connection: keep-alive\r\n\r\n");
20452 mock_reads3.emplace_back(
20453 "HTTP/1.1 401 Unauthorized\r\n"
20454 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20455 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020456 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420457 mock_writes3.emplace_back(
20458 "GET / HTTP/1.1\r\n"
20459 "Host: www.example.org\r\n"
20460 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020461 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420462 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20463 mock_reads3.emplace_back(
20464 "HTTP/1.1 200 OK\r\n"
20465 "Content-Length: 0\r\n\r\n");
David Benjaminbac8dff2019-08-07 01:30:4120466 // The client makes another request. This should reuse the socket with all
20467 // credentials cached.
20468 mock_writes3.emplace_back(
20469 "GET / HTTP/1.1\r\n"
20470 "Host: www.example.org\r\n"
20471 "Connection: keep-alive\r\n"
20472 // Authenticate as user:pass.
20473 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20474 mock_reads3.emplace_back(
20475 "HTTP/1.1 200 OK\r\n"
20476 "Content-Length: 0\r\n\r\n");
David Benjamin2eb827f2019-04-29 18:31:0420477 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20478 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020479 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20480 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420481
20482 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20483
20484 // Start the request.
20485 TestCompletionCallback callback;
20486 auto trans =
20487 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20488 int rv = callback.GetResult(
20489 trans->Start(&request, callback.callback(), NetLogWithSource()));
20490
20491 // Handle the proxy client certificate challenge.
20492 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20493 SSLCertRequestInfo* cert_request_info =
20494 trans->GetResponseInfo()->cert_request_info.get();
20495 ASSERT_TRUE(cert_request_info);
20496 EXPECT_TRUE(cert_request_info->is_proxy);
20497 EXPECT_EQ(cert_request_info->host_and_port,
20498 cert_request_info_proxy->host_and_port);
20499 rv = callback.GetResult(trans->RestartWithCertificate(
20500 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20501 callback.callback()));
20502
20503 // Handle the proxy HTTP auth challenge.
20504 ASSERT_THAT(rv, IsOk());
20505 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20506 EXPECT_TRUE(
20507 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20508 rv = callback.GetResult(trans->RestartWithAuth(
20509 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20510 callback.callback()));
20511
20512 // Handle the origin client certificate challenge.
20513 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20514 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20515 ASSERT_TRUE(cert_request_info);
20516 EXPECT_FALSE(cert_request_info->is_proxy);
20517 EXPECT_EQ(cert_request_info->host_and_port,
20518 cert_request_info_origin->host_and_port);
20519 rv = callback.GetResult(trans->RestartWithCertificate(
20520 identity_origin->certificate(), identity_origin->ssl_private_key(),
20521 callback.callback()));
20522
20523 // Handle the origin HTTP auth challenge.
20524 ASSERT_THAT(rv, IsOk());
20525 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20526 EXPECT_TRUE(
20527 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20528 rv = callback.GetResult(trans->RestartWithAuth(
20529 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20530 callback.callback()));
20531
20532 // The request completes.
20533 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020534 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120535
20536 // Make a second request. This time all credentials are cached.
20537 trans =
20538 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20539 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20540 NetLogWithSource())),
20541 IsOk());
20542 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420543}
20544
20545// Test the proxy and origin server each requesting both TLS client certificates
20546// and HTTP auth and each HTTP auth closing the connection. This is a regression
20547// test for https://crbug.com/946406.
20548TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
20549 // Note these hosts must match the CheckBasic*Auth() functions.
20550 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20551 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20552
20553 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20554 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20555
20556 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20557 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20558 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20559 ASSERT_TRUE(identity_proxy);
20560
20561 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20562 cert_request_info_origin->host_and_port =
20563 HostPortPair("www.example.org", 443);
20564
20565 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20566 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20567 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20568 ASSERT_TRUE(identity_origin);
20569
20570 HttpRequestInfo request;
20571 request.method = "GET";
20572 request.url = GURL("https://www.example.org/");
20573 request.traffic_annotation =
20574 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20575
David Benjamin7ebab032019-04-30 21:51:3020576 // First, the client connects to the proxy, which requests a client
20577 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420578 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20579 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20580 ssl_proxy1.expected_send_client_cert = false;
20581 StaticSocketDataProvider data1;
20582 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020583 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420584
David Benjamin7ebab032019-04-30 21:51:3020585 // The client responds with a certificate on a new connection. The handshake
20586 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420587 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20588 ssl_proxy2.expected_send_client_cert = true;
20589 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020590 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420591 std::vector<MockWrite> mock_writes2;
20592 std::vector<MockRead> mock_reads2;
20593 mock_writes2.emplace_back(
20594 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20595 "Host: www.example.org:443\r\n"
20596 "Proxy-Connection: keep-alive\r\n\r\n");
20597 mock_reads2.emplace_back(
20598 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20599 "Content-Length: 0\r\n"
20600 "Proxy-Connection: close\r\n"
20601 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20602 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20603 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020604 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0420605
David Benjamin7ebab032019-04-30 21:51:3020606 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0420607 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20608 ssl_proxy3.expected_send_client_cert = true;
20609 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20610 std::vector<MockWrite> mock_writes3;
20611 std::vector<MockRead> mock_reads3;
20612 mock_writes3.emplace_back(
20613 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20614 "Host: www.example.org:443\r\n"
20615 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020616 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420617 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20618 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20619 // The origin requests client certificates.
20620 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20621 ssl_origin3.cert_request_info = cert_request_info_origin.get();
20622 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20623 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020624 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20625 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420626
David Benjamin7ebab032019-04-30 21:51:3020627 // The client responds to the origin client certificate request on a new
20628 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420629 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
20630 ssl_proxy4.expected_send_client_cert = true;
20631 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
20632 std::vector<MockWrite> mock_writes4;
20633 std::vector<MockRead> mock_reads4;
20634 mock_writes4.emplace_back(
20635 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20636 "Host: www.example.org:443\r\n"
20637 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020638 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420639 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20640 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20641 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
20642 ssl_origin4.expected_send_client_cert = true;
20643 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020644 // The client sends the origin HTTP request, which results in another HTTP
20645 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0420646 mock_writes4.emplace_back(
20647 "GET / HTTP/1.1\r\n"
20648 "Host: www.example.org\r\n"
20649 "Connection: keep-alive\r\n\r\n");
20650 mock_reads4.emplace_back(
20651 "HTTP/1.1 401 Unauthorized\r\n"
20652 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20653 "Connection: close\r\n"
20654 "Content-Length: 0\r\n\r\n");
20655 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
20656 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3020657 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
20658 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0420659
David Benjamin7ebab032019-04-30 21:51:3020660 // The client retries with credentials on a new connection, and the request
20661 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420662 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
20663 ssl_proxy5.expected_send_client_cert = true;
20664 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
20665 std::vector<MockWrite> mock_writes5;
20666 std::vector<MockRead> mock_reads5;
20667 mock_writes5.emplace_back(
20668 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20669 "Host: www.example.org:443\r\n"
20670 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020671 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420672 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20673 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20674 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
20675 ssl_origin5.expected_send_client_cert = true;
20676 ssl_origin5.expected_client_cert = identity_origin->certificate();
20677 mock_writes5.emplace_back(
20678 "GET / HTTP/1.1\r\n"
20679 "Host: www.example.org\r\n"
20680 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020681 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420682 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20683 mock_reads5.emplace_back(
20684 "HTTP/1.1 200 OK\r\n"
20685 "Connection: close\r\n"
20686 "Content-Length: 0\r\n\r\n");
20687 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
20688 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3020689 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
20690 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0420691
David Benjaminbac8dff2019-08-07 01:30:4120692 // The client makes a second request. This needs yet another connection, but
20693 // all credentials are cached.
20694 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
20695 ssl_proxy6.expected_send_client_cert = true;
20696 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
20697 std::vector<MockWrite> mock_writes6;
20698 std::vector<MockRead> mock_reads6;
20699 mock_writes6.emplace_back(
20700 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20701 "Host: www.example.org:443\r\n"
20702 "Proxy-Connection: keep-alive\r\n"
20703 // Authenticate as proxyuser:proxypass.
20704 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20705 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20706 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
20707 ssl_origin6.expected_send_client_cert = true;
20708 ssl_origin6.expected_client_cert = identity_origin->certificate();
20709 mock_writes6.emplace_back(
20710 "GET / HTTP/1.1\r\n"
20711 "Host: www.example.org\r\n"
20712 "Connection: keep-alive\r\n"
20713 // Authenticate as user:pass.
20714 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20715 mock_reads6.emplace_back(
20716 "HTTP/1.1 200 OK\r\n"
20717 "Connection: close\r\n"
20718 "Content-Length: 0\r\n\r\n");
20719 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
20720 session_deps_.socket_factory->AddSocketDataProvider(&data6);
20721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
20722 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
20723
David Benjamin2eb827f2019-04-29 18:31:0420724 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20725
20726 // Start the request.
20727 TestCompletionCallback callback;
20728 auto trans =
20729 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20730 int rv = callback.GetResult(
20731 trans->Start(&request, callback.callback(), NetLogWithSource()));
20732
20733 // Handle the proxy client certificate challenge.
20734 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20735 SSLCertRequestInfo* cert_request_info =
20736 trans->GetResponseInfo()->cert_request_info.get();
20737 ASSERT_TRUE(cert_request_info);
20738 EXPECT_TRUE(cert_request_info->is_proxy);
20739 EXPECT_EQ(cert_request_info->host_and_port,
20740 cert_request_info_proxy->host_and_port);
20741 rv = callback.GetResult(trans->RestartWithCertificate(
20742 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20743 callback.callback()));
20744
20745 // Handle the proxy HTTP auth challenge.
20746 ASSERT_THAT(rv, IsOk());
20747 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20748 EXPECT_TRUE(
20749 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20750 rv = callback.GetResult(trans->RestartWithAuth(
20751 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20752 callback.callback()));
20753
20754 // Handle the origin client certificate challenge.
20755 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20756 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20757 ASSERT_TRUE(cert_request_info);
20758 EXPECT_FALSE(cert_request_info->is_proxy);
20759 EXPECT_EQ(cert_request_info->host_and_port,
20760 cert_request_info_origin->host_and_port);
20761 rv = callback.GetResult(trans->RestartWithCertificate(
20762 identity_origin->certificate(), identity_origin->ssl_private_key(),
20763 callback.callback()));
20764
20765 // Handle the origin HTTP auth challenge.
20766 ASSERT_THAT(rv, IsOk());
20767 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20768 EXPECT_TRUE(
20769 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20770 rv = callback.GetResult(trans->RestartWithAuth(
20771 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20772 callback.callback()));
20773
20774 // The request completes.
20775 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020776 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjaminbac8dff2019-08-07 01:30:4120777
20778 // Make a second request. This time all credentials are cached.
20779 trans =
20780 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20781 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20782 NetLogWithSource())),
20783 IsOk());
20784 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin7ebab032019-04-30 21:51:3020785}
20786
20787// Test the proxy requesting HTTP auth and the server requesting TLS client
20788// certificates. This is a regression test for https://crbug.com/946406.
20789TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
20790 // Note these hosts must match the CheckBasic*Auth() functions.
20791 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20792 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20793
20794 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20795 cert_request_info_origin->host_and_port =
20796 HostPortPair("www.example.org", 443);
20797
20798 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20799 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20800 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20801 ASSERT_TRUE(identity_origin);
20802
20803 HttpRequestInfo request;
20804 request.method = "GET";
20805 request.url = GURL("https://www.example.org/");
20806 request.traffic_annotation =
20807 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20808
20809 // The client connects to the proxy. The handshake succeeds.
20810 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
20811 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20812 std::vector<MockWrite> mock_writes1;
20813 std::vector<MockRead> mock_reads1;
20814 mock_writes1.emplace_back(
20815 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20816 "Host: www.example.org:443\r\n"
20817 "Proxy-Connection: keep-alive\r\n\r\n");
20818 mock_reads1.emplace_back(
20819 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20820 "Content-Length: 0\r\n"
20821 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20822 // The client retries with credentials, and the request finally succeeds.
20823 mock_writes1.emplace_back(
20824 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20825 "Host: www.example.org:443\r\n"
20826 "Proxy-Connection: keep-alive\r\n"
20827 // Authenticate as proxyuser:proxypass.
20828 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20829 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20830 // The origin requests client certificates.
20831 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20832 ssl_origin1.cert_request_info = cert_request_info_origin.get();
20833 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
20834 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20835 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20836 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
20837
20838 // The client responds to the origin client certificate request on a new
20839 // connection.
20840 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20841 std::vector<MockWrite> mock_writes2;
20842 std::vector<MockRead> mock_reads2;
20843 mock_writes2.emplace_back(
20844 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20845 "Host: www.example.org:443\r\n"
20846 "Proxy-Connection: keep-alive\r\n"
20847 // Authenticate as proxyuser:proxypass.
20848 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20849 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20850 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
20851 ssl_origin2.expected_send_client_cert = true;
20852 ssl_origin2.expected_client_cert = identity_origin->certificate();
20853 // The client sends the origin HTTP request, which succeeds.
20854 mock_writes2.emplace_back(
20855 "GET / HTTP/1.1\r\n"
20856 "Host: www.example.org\r\n"
20857 "Connection: keep-alive\r\n\r\n");
20858 mock_reads2.emplace_back(
20859 "HTTP/1.1 200 OK\r\n"
20860 "Content-Length: 0\r\n\r\n");
20861 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20862 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20863 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20864 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
20865
20866 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20867
20868 // Start the request.
20869 TestCompletionCallback callback;
20870 auto trans =
20871 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20872 int rv = callback.GetResult(
20873 trans->Start(&request, callback.callback(), NetLogWithSource()));
20874
20875 // Handle the proxy HTTP auth challenge.
20876 ASSERT_THAT(rv, IsOk());
20877 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20878 EXPECT_TRUE(
20879 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20880 rv = callback.GetResult(trans->RestartWithAuth(
20881 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20882 callback.callback()));
20883
20884 // Handle the origin client certificate challenge.
20885 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20886 SSLCertRequestInfo* cert_request_info =
20887 trans->GetResponseInfo()->cert_request_info.get();
20888 ASSERT_TRUE(cert_request_info);
20889 EXPECT_FALSE(cert_request_info->is_proxy);
20890 EXPECT_EQ(cert_request_info->host_and_port,
20891 cert_request_info_origin->host_and_port);
20892 rv = callback.GetResult(trans->RestartWithCertificate(
20893 identity_origin->certificate(), identity_origin->ssl_private_key(),
20894 callback.callback()));
20895
20896 // The request completes.
20897 ASSERT_THAT(rv, IsOk());
20898 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420899}
20900
David Benjamin6e673a82019-04-30 22:52:5820901// Test that socket reuse works with client certificates.
20902TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
20903 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
20904 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
20905
20906 std::unique_ptr<FakeClientCertIdentity> identity =
20907 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20908 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20909 ASSERT_TRUE(identity);
20910
20911 HttpRequestInfo request1;
20912 request1.method = "GET";
20913 request1.url = GURL("https://www.example.org/a");
20914 request1.traffic_annotation =
20915 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20916
20917 HttpRequestInfo request2;
20918 request2.method = "GET";
20919 request2.url = GURL("https://www.example.org/b");
20920 request2.traffic_annotation =
20921 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20922
20923 // The first connection results in a client certificate request.
20924 StaticSocketDataProvider data1;
20925 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20926 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20927 ssl1.cert_request_info = cert_request_info.get();
20928 ssl1.expected_send_client_cert = false;
20929 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20930
20931 // The second connection succeeds and is usable for both requests.
20932 MockWrite mock_writes[] = {
20933 MockWrite("GET /a HTTP/1.1\r\n"
20934 "Host: www.example.org\r\n"
20935 "Connection: keep-alive\r\n\r\n"),
20936 MockWrite("GET /b HTTP/1.1\r\n"
20937 "Host: www.example.org\r\n"
20938 "Connection: keep-alive\r\n\r\n"),
20939 };
20940 MockRead mock_reads[] = {
20941 MockRead("HTTP/1.1 200 OK\r\n"
20942 "Content-Length: 0\r\n\r\n"),
20943 MockRead("HTTP/1.1 200 OK\r\n"
20944 "Content-Length: 0\r\n\r\n"),
20945 };
20946 StaticSocketDataProvider data2(mock_reads, mock_writes);
20947 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20948 SSLSocketDataProvider ssl2(ASYNC, OK);
20949 ssl2.expected_send_client_cert = true;
20950 ssl2.expected_client_cert = identity->certificate();
20951 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20952
20953 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20954
20955 // Start the first request. It succeeds after providing client certificates.
20956 TestCompletionCallback callback;
20957 auto trans =
20958 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20959 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
20960 NetLogWithSource())),
20961 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20962
20963 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
20964 ASSERT_TRUE(info);
20965 EXPECT_FALSE(info->is_proxy);
20966 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
20967
20968 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
20969 identity->certificate(), identity->ssl_private_key(),
20970 callback.callback())),
20971 IsOk());
20972 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20973
20974 // Make the second request. It completes without requesting client
20975 // certificates.
20976 trans =
20977 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20978 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
20979 NetLogWithSource())),
20980 IsOk());
20981 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20982}
20983
Matt Menke166443c2019-05-24 18:45:5920984// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
20985// sequence with two different NetworkIsolationKeys, the first and last have the
20986// same key, the second a different one. Checks that the requests are
20987// partitioned across sockets as expected.
20988TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
Shivani Sharma8ae506c2019-07-21 21:08:2720989 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
20990 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
20991 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
20992 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menke166443c2019-05-24 18:45:5920993
20994 for (bool partition_connections : {false, true}) {
20995 SCOPED_TRACE(partition_connections);
20996
20997 base::test::ScopedFeatureList feature_list;
20998 if (partition_connections) {
20999 feature_list.InitAndEnableFeature(
21000 features::kPartitionConnectionsByNetworkIsolationKey);
21001 } else {
21002 feature_list.InitAndDisableFeature(
21003 features::kPartitionConnectionsByNetworkIsolationKey);
21004 }
21005
21006 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21007
21008 // Reads and writes for the unpartitioned case, where only one socket is
21009 // used.
21010
21011 const MockWrite kUnpartitionedWrites[] = {
21012 MockWrite("GET /1 HTTP/1.1\r\n"
21013 "Host: foo.test\r\n"
21014 "Connection: keep-alive\r\n\r\n"),
21015 MockWrite("GET /2 HTTP/1.1\r\n"
21016 "Host: foo.test\r\n"
21017 "Connection: keep-alive\r\n\r\n"),
21018 MockWrite("GET /3 HTTP/1.1\r\n"
21019 "Host: foo.test\r\n"
21020 "Connection: keep-alive\r\n\r\n"),
21021 };
21022
21023 const MockRead kUnpartitionedReads[] = {
21024 MockRead("HTTP/1.1 200 OK\r\n"
21025 "Connection: keep-alive\r\n"
21026 "Content-Length: 1\r\n\r\n"
21027 "1"),
21028 MockRead("HTTP/1.1 200 OK\r\n"
21029 "Connection: keep-alive\r\n"
21030 "Content-Length: 1\r\n\r\n"
21031 "2"),
21032 MockRead("HTTP/1.1 200 OK\r\n"
21033 "Connection: keep-alive\r\n"
21034 "Content-Length: 1\r\n\r\n"
21035 "3"),
21036 };
21037
21038 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
21039 kUnpartitionedWrites);
21040
21041 // Reads and writes for the partitioned case, where two sockets are used.
21042
21043 const MockWrite kPartitionedWrites1[] = {
21044 MockWrite("GET /1 HTTP/1.1\r\n"
21045 "Host: foo.test\r\n"
21046 "Connection: keep-alive\r\n\r\n"),
21047 MockWrite("GET /3 HTTP/1.1\r\n"
21048 "Host: foo.test\r\n"
21049 "Connection: keep-alive\r\n\r\n"),
21050 };
21051
21052 const MockRead kPartitionedReads1[] = {
21053 MockRead("HTTP/1.1 200 OK\r\n"
21054 "Connection: keep-alive\r\n"
21055 "Content-Length: 1\r\n\r\n"
21056 "1"),
21057 MockRead("HTTP/1.1 200 OK\r\n"
21058 "Connection: keep-alive\r\n"
21059 "Content-Length: 1\r\n\r\n"
21060 "3"),
21061 };
21062
21063 const MockWrite kPartitionedWrites2[] = {
21064 MockWrite("GET /2 HTTP/1.1\r\n"
21065 "Host: foo.test\r\n"
21066 "Connection: keep-alive\r\n\r\n"),
21067 };
21068
21069 const MockRead kPartitionedReads2[] = {
21070 MockRead("HTTP/1.1 200 OK\r\n"
21071 "Connection: keep-alive\r\n"
21072 "Content-Length: 1\r\n\r\n"
21073 "2"),
21074 };
21075
21076 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
21077 kPartitionedWrites1);
21078 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
21079 kPartitionedWrites2);
21080
21081 if (partition_connections) {
21082 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21083 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21084 } else {
21085 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
21086 }
21087
21088 TestCompletionCallback callback;
21089 HttpRequestInfo request1;
21090 request1.method = "GET";
21091 request1.url = GURL("http://foo.test/1");
21092 request1.traffic_annotation =
21093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21094 request1.network_isolation_key = network_isolation_key1;
21095 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21096 session.get());
21097 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21098 EXPECT_THAT(callback.GetResult(rv), IsOk());
21099 std::string response_data1;
21100 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21101 EXPECT_EQ("1", response_data1);
21102 trans1.reset();
21103
21104 HttpRequestInfo request2;
21105 request2.method = "GET";
21106 request2.url = GURL("http://foo.test/2");
21107 request2.traffic_annotation =
21108 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21109 request2.network_isolation_key = network_isolation_key2;
21110 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21111 session.get());
21112 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21113 EXPECT_THAT(callback.GetResult(rv), IsOk());
21114 std::string response_data2;
21115 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21116 EXPECT_EQ("2", response_data2);
21117 trans2.reset();
21118
21119 HttpRequestInfo request3;
21120 request3.method = "GET";
21121 request3.url = GURL("http://foo.test/3");
21122 request3.traffic_annotation =
21123 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21124 request3.network_isolation_key = network_isolation_key1;
21125 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
21126 session.get());
21127 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21128 EXPECT_THAT(callback.GetResult(rv), IsOk());
21129 std::string response_data3;
21130 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21131 EXPECT_EQ("3", response_data3);
21132 trans3.reset();
21133 }
21134}
21135
Matt Menkeae58eeb2019-05-24 21:09:5021136TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
Shivani Sharma8ae506c2019-07-21 21:08:2721137 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21138 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21139 NetworkIsolationKey network_isolation_key1(kOrigin1, kOrigin1);
21140 NetworkIsolationKey network_isolation_key2(kOrigin2, kOrigin2);
Matt Menkeae58eeb2019-05-24 21:09:5021141
21142 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
21143 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
21144 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
21145 // the same way as the HTTP over H2 proxy case.
21146 for (bool use_proxy : {false, true}) {
21147 SCOPED_TRACE(use_proxy);
21148 if (use_proxy) {
21149 session_deps_.proxy_resolution_service =
21150 ProxyResolutionService::CreateFixedFromPacResult(
21151 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
21152 } else {
21153 session_deps_.proxy_resolution_service =
21154 ProxyResolutionService::CreateDirect();
21155 }
21156 const char* url1 = nullptr;
21157 const char* url2 = nullptr;
21158 const char* url3 = nullptr;
21159 if (use_proxy) {
21160 url1 = "http://foo.test/1";
21161 url2 = "http://foo.test/2";
21162 url3 = "http://foo.test/3";
21163 } else {
21164 url1 = "https://foo.test/1";
21165 url2 = "https://foo.test/2";
21166 url3 = "https://foo.test/3";
21167 }
21168
21169 for (bool partition_connections : {false, true}) {
21170 SCOPED_TRACE(partition_connections);
21171
21172 base::test::ScopedFeatureList feature_list;
21173 if (partition_connections) {
21174 feature_list.InitAndEnableFeature(
21175 features::kPartitionConnectionsByNetworkIsolationKey);
21176 } else {
21177 feature_list.InitAndDisableFeature(
21178 features::kPartitionConnectionsByNetworkIsolationKey);
21179 }
21180
21181 std::unique_ptr<HttpNetworkSession> session(
21182 CreateSession(&session_deps_));
21183
21184 // Reads and writes for the unpartitioned case, where only one socket is
21185 // used.
21186
21187 SpdyTestUtil spdy_util;
21188 spdy::SpdySerializedFrame unpartitioned_req1(
21189 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
21190 spdy::SpdySerializedFrame unpartitioned_response1(
21191 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
21192 spdy::SpdySerializedFrame unpartitioned_body1(
21193 spdy_util.ConstructSpdyDataFrame(1, "1", true));
21194 spdy_util.UpdateWithStreamDestruction(1);
21195
21196 spdy::SpdySerializedFrame unpartitioned_req2(
21197 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
21198 spdy::SpdySerializedFrame unpartitioned_response2(
21199 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
21200 spdy::SpdySerializedFrame unpartitioned_body2(
21201 spdy_util.ConstructSpdyDataFrame(3, "2", true));
21202 spdy_util.UpdateWithStreamDestruction(3);
21203
21204 spdy::SpdySerializedFrame unpartitioned_req3(
21205 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
21206 spdy::SpdySerializedFrame unpartitioned_response3(
21207 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
21208 spdy::SpdySerializedFrame unpartitioned_body3(
21209 spdy_util.ConstructSpdyDataFrame(5, "3", true));
21210
21211 const MockWrite kUnpartitionedWrites[] = {
21212 CreateMockWrite(unpartitioned_req1, 0),
21213 CreateMockWrite(unpartitioned_req2, 3),
21214 CreateMockWrite(unpartitioned_req3, 6),
21215 };
21216
21217 const MockRead kUnpartitionedReads[] = {
21218 CreateMockRead(unpartitioned_response1, 1),
21219 CreateMockRead(unpartitioned_body1, 2),
21220 CreateMockRead(unpartitioned_response2, 4),
21221 CreateMockRead(unpartitioned_body2, 5),
21222 CreateMockRead(unpartitioned_response3, 7),
21223 CreateMockRead(unpartitioned_body3, 8),
21224 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
21225 };
21226
21227 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
21228 kUnpartitionedWrites);
21229
21230 // Reads and writes for the partitioned case, where two sockets are used.
21231
21232 SpdyTestUtil spdy_util2;
21233 spdy::SpdySerializedFrame partitioned_req1(
21234 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
21235 spdy::SpdySerializedFrame partitioned_response1(
21236 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
21237 spdy::SpdySerializedFrame partitioned_body1(
21238 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
21239 spdy_util2.UpdateWithStreamDestruction(1);
21240
21241 spdy::SpdySerializedFrame partitioned_req3(
21242 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
21243 spdy::SpdySerializedFrame partitioned_response3(
21244 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
21245 spdy::SpdySerializedFrame partitioned_body3(
21246 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
21247
21248 const MockWrite kPartitionedWrites1[] = {
21249 CreateMockWrite(partitioned_req1, 0),
21250 CreateMockWrite(partitioned_req3, 3),
21251 };
21252
21253 const MockRead kPartitionedReads1[] = {
21254 CreateMockRead(partitioned_response1, 1),
21255 CreateMockRead(partitioned_body1, 2),
21256 CreateMockRead(partitioned_response3, 4),
21257 CreateMockRead(partitioned_body3, 5),
21258 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
21259 };
21260
21261 SpdyTestUtil spdy_util3;
21262 spdy::SpdySerializedFrame partitioned_req2(
21263 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
21264 spdy::SpdySerializedFrame partitioned_response2(
21265 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
21266 spdy::SpdySerializedFrame partitioned_body2(
21267 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
21268
21269 const MockWrite kPartitionedWrites2[] = {
21270 CreateMockWrite(partitioned_req2, 0),
21271 };
21272
21273 const MockRead kPartitionedReads2[] = {
21274 CreateMockRead(partitioned_response2, 1),
21275 CreateMockRead(partitioned_body2, 2),
21276 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21277 };
21278
21279 SequencedSocketData partitioned_data1(kPartitionedReads1,
21280 kPartitionedWrites1);
21281 SequencedSocketData partitioned_data2(kPartitionedReads2,
21282 kPartitionedWrites2);
21283
21284 // No need to segment SSLDataProviders by whether or not partitioning is
21285 // enabled.
21286 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21287 ssl_data1.next_proto = kProtoHTTP2;
21288 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21289 ssl_data2.next_proto = kProtoHTTP2;
21290
21291 if (partition_connections) {
21292 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21293 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21294 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21296 } else {
21297 session_deps_.socket_factory->AddSocketDataProvider(
21298 &unpartitioned_data);
21299 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21300 }
21301
21302 TestCompletionCallback callback;
21303 HttpRequestInfo request1;
21304 request1.method = "GET";
21305 request1.url = GURL(url1);
21306 request1.traffic_annotation =
21307 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21308 request1.network_isolation_key = network_isolation_key1;
21309 auto trans1 =
21310 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21311 int rv =
21312 trans1->Start(&request1, callback.callback(), NetLogWithSource());
21313 EXPECT_THAT(callback.GetResult(rv), IsOk());
21314 std::string response_data1;
21315 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21316 EXPECT_EQ("1", response_data1);
21317 trans1.reset();
21318
21319 HttpRequestInfo request2;
21320 request2.method = "GET";
21321 request2.url = GURL(url2);
21322 request2.traffic_annotation =
21323 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21324 request2.network_isolation_key = network_isolation_key2;
21325 auto trans2 =
21326 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21327 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21328 EXPECT_THAT(callback.GetResult(rv), IsOk());
21329 std::string response_data2;
21330 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21331 EXPECT_EQ("2", response_data2);
21332 trans2.reset();
21333
21334 HttpRequestInfo request3;
21335 request3.method = "GET";
21336 request3.url = GURL(url3);
21337 request3.traffic_annotation =
21338 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21339 request3.network_isolation_key = network_isolation_key1;
21340 auto trans3 =
21341 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21342 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21343 EXPECT_THAT(callback.GetResult(rv), IsOk());
21344 std::string response_data3;
21345 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21346 EXPECT_EQ("3", response_data3);
21347 trans3.reset();
21348 }
21349 }
21350}
21351
Matt Menke7281f872019-06-25 19:29:2521352// Preconnect two sockets with different NetworkIsolationKeys when
21353// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
21354// request and make sure the correct socket is used. Loops three times,
21355// expecting to use the first preconnect, second preconnect, and neither.
21356TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
21357 base::test::ScopedFeatureList feature_list;
21358 feature_list.InitAndEnableFeature(
21359 features::kPartitionConnectionsByNetworkIsolationKey);
21360
21361 enum class TestCase {
21362 kUseFirstPreconnect,
21363 kUseSecondPreconnect,
21364 kDontUsePreconnect,
21365 };
21366
Shivani Sharma8ae506c2019-07-21 21:08:2721367 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21368 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21369 const auto kOrigin3 = url::Origin::Create(GURL("http://origin3/"));
21370 NetworkIsolationKey preconnect1_isolation_key(kOrigin1, kOrigin1);
21371 NetworkIsolationKey preconnect2_isolation_key(kOrigin2, kOrigin2);
21372 NetworkIsolationKey not_preconnected_isolation_key(kOrigin3, kOrigin3);
Matt Menke7281f872019-06-25 19:29:2521373
21374 // Test that only preconnects with
21375 for (TestCase test_case :
21376 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
21377 TestCase::kDontUsePreconnect}) {
21378 SpdySessionDependencies session_deps;
21379 // Make DNS lookups completely synchronously, so preconnects complete
21380 // immediately.
21381 session_deps.host_resolver->set_synchronous_mode(true);
21382
21383 const MockWrite kMockWrites[] = {
21384 MockWrite(ASYNC, 0,
21385 "GET / HTTP/1.1\r\n"
21386 "Host: www.foo.com\r\n"
21387 "Connection: keep-alive\r\n\r\n"),
21388 };
21389
21390 const MockRead kMockReads[] = {
21391 MockRead(ASYNC, 1,
21392 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
21393 "hello"),
21394 };
21395
21396 // Used for the socket that will actually be used, which may or may not be
21397 // one of the preconnects
21398 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
21399 kMockReads, kMockWrites);
21400
21401 // Used for the preconnects that won't actually be used.
21402 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
21403 base::span<const MockRead>(),
21404 base::span<const MockWrite>());
21405 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
21406 base::span<const MockRead>(),
21407 base::span<const MockWrite>());
21408
21409 NetworkIsolationKey network_isolation_key_for_request;
21410
21411 switch (test_case) {
21412 case TestCase::kUseFirstPreconnect:
21413 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21414 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21415 network_isolation_key_for_request = preconnect1_isolation_key;
21416 break;
21417 case TestCase::kUseSecondPreconnect:
21418 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21419 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21420 network_isolation_key_for_request = preconnect2_isolation_key;
21421 break;
21422 case TestCase::kDontUsePreconnect:
21423 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21424 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21425 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21426 network_isolation_key_for_request = not_preconnected_isolation_key;
21427 break;
21428 }
21429
21430 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
21431
21432 // Preconnect sockets.
21433 HttpRequestInfo request;
21434 request.method = "GET";
21435 request.url = GURL("http://www.foo.com/");
21436 request.traffic_annotation =
21437 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21438
21439 request.network_isolation_key = preconnect1_isolation_key;
21440 session->http_stream_factory()->PreconnectStreams(1, request);
21441
21442 request.network_isolation_key = preconnect2_isolation_key;
21443 session->http_stream_factory()->PreconnectStreams(1, request);
21444
21445 request.network_isolation_key = network_isolation_key_for_request;
21446
21447 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21448
21449 // Make the request.
21450 TestCompletionCallback callback;
21451
21452 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21453
21454 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
21455 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21456
21457 rv = callback.WaitForResult();
21458 EXPECT_THAT(rv, IsOk());
21459
21460 const HttpResponseInfo* response = trans.GetResponseInfo();
21461 ASSERT_TRUE(response);
21462 ASSERT_TRUE(response->headers);
21463 EXPECT_EQ(200, response->headers->response_code());
21464
21465 std::string response_data;
21466 rv = ReadTransaction(&trans, &response_data);
21467 EXPECT_THAT(rv, IsOk());
21468 EXPECT_EQ("hello", response_data);
21469
21470 if (test_case != TestCase::kDontUsePreconnect) {
21471 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21472 } else {
21473 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
21474 }
21475 }
21476}
21477
David Benjamin6f2da652019-06-26 23:36:3521478// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21479// cache is isolated.
21480TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
21481 base::test::ScopedFeatureList feature_list;
21482 feature_list.InitWithFeatures(
21483 {features::kPartitionConnectionsByNetworkIsolationKey,
21484 features::kPartitionSSLSessionsByNetworkIsolationKey},
21485 {});
21486
Shivani Sharma8ae506c2019-07-21 21:08:2721487 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21488 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21489 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21490 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521491 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21492
21493 // The server always sends Connection: close, so each request goes over a
21494 // distinct socket.
21495
21496 const MockWrite kWrites1[] = {
21497 MockWrite("GET /1 HTTP/1.1\r\n"
21498 "Host: foo.test\r\n"
21499 "Connection: keep-alive\r\n\r\n")};
21500
21501 const MockRead kReads1[] = {
21502 MockRead("HTTP/1.1 200 OK\r\n"
21503 "Connection: close\r\n"
21504 "Content-Length: 1\r\n\r\n"
21505 "1")};
21506
21507 const MockWrite kWrites2[] = {
21508 MockWrite("GET /2 HTTP/1.1\r\n"
21509 "Host: foo.test\r\n"
21510 "Connection: keep-alive\r\n\r\n")};
21511
21512 const MockRead kReads2[] = {
21513 MockRead("HTTP/1.1 200 OK\r\n"
21514 "Connection: close\r\n"
21515 "Content-Length: 1\r\n\r\n"
21516 "2")};
21517
21518 const MockWrite kWrites3[] = {
21519 MockWrite("GET /3 HTTP/1.1\r\n"
21520 "Host: foo.test\r\n"
21521 "Connection: keep-alive\r\n\r\n")};
21522
21523 const MockRead kReads3[] = {
21524 MockRead("HTTP/1.1 200 OK\r\n"
21525 "Connection: close\r\n"
21526 "Content-Length: 1\r\n\r\n"
21527 "3")};
21528
21529 StaticSocketDataProvider data1(kReads1, kWrites1);
21530 StaticSocketDataProvider data2(kReads2, kWrites2);
21531 StaticSocketDataProvider data3(kReads3, kWrites3);
21532 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21533 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21534 session_deps_.socket_factory->AddSocketDataProvider(&data3);
21535
21536 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21537 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
21538 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
21539 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21540 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
21541 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
21542 SSLSocketDataProvider ssl_data3(ASYNC, OK);
21543 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
21544 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
21545 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21546 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21547 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
21548
21549 TestCompletionCallback callback;
21550 HttpRequestInfo request1;
21551 request1.method = "GET";
21552 request1.url = GURL("https://foo.test/1");
21553 request1.traffic_annotation =
21554 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21555 request1.network_isolation_key = kNetworkIsolationKey1;
21556 auto trans1 =
21557 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21558 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21559 EXPECT_THAT(callback.GetResult(rv), IsOk());
21560 std::string response_data1;
21561 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21562 EXPECT_EQ("1", response_data1);
21563 trans1.reset();
21564
21565 HttpRequestInfo request2;
21566 request2.method = "GET";
21567 request2.url = GURL("https://foo.test/2");
21568 request2.traffic_annotation =
21569 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21570 request2.network_isolation_key = kNetworkIsolationKey2;
21571 auto trans2 =
21572 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21573 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21574 EXPECT_THAT(callback.GetResult(rv), IsOk());
21575 std::string response_data2;
21576 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21577 EXPECT_EQ("2", response_data2);
21578 trans2.reset();
21579
21580 HttpRequestInfo request3;
21581 request3.method = "GET";
21582 request3.url = GURL("https://foo.test/3");
21583 request3.traffic_annotation =
21584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21585 request3.network_isolation_key = kNetworkIsolationKey1;
21586 auto trans3 =
21587 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21588 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21589 EXPECT_THAT(callback.GetResult(rv), IsOk());
21590 std::string response_data3;
21591 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21592 EXPECT_EQ("3", response_data3);
21593 trans3.reset();
21594}
21595
21596// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21597// cache is isolated, for both origins and proxies.
21598TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
21599 base::test::ScopedFeatureList feature_list;
21600 feature_list.InitWithFeatures(
21601 {features::kPartitionConnectionsByNetworkIsolationKey,
21602 features::kPartitionSSLSessionsByNetworkIsolationKey},
21603 {});
21604
21605 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21606 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21607
Shivani Sharma8ae506c2019-07-21 21:08:2721608 const auto kOrigin1 = url::Origin::Create(GURL("http://origin1/"));
21609 const auto kOrigin2 = url::Origin::Create(GURL("http://origin2/"));
21610 const NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
21611 const NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
David Benjamin6f2da652019-06-26 23:36:3521612 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21613
21614 // Make both a tunneled and non-tunneled request.
21615 HttpRequestInfo request1;
21616 request1.method = "GET";
21617 request1.url = GURL("https://foo.test/1");
21618 request1.traffic_annotation =
21619 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21620 request1.network_isolation_key = kNetworkIsolationKey1;
21621
21622 HttpRequestInfo request2;
21623 request2.method = "GET";
21624 request2.url = GURL("http://foo.test/2");
21625 request2.traffic_annotation =
21626 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21627 request2.network_isolation_key = kNetworkIsolationKey2;
21628
21629 const MockWrite kWrites1[] = {
21630 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
21631 "Host: foo.test:443\r\n"
21632 "Proxy-Connection: keep-alive\r\n\r\n"),
21633 MockWrite("GET /1 HTTP/1.1\r\n"
21634 "Host: foo.test\r\n"
21635 "Connection: keep-alive\r\n\r\n")};
21636
21637 const MockRead kReads1[] = {
21638 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
21639 MockRead("HTTP/1.1 200 OK\r\n"
21640 "Connection: close\r\n"
21641 "Content-Length: 1\r\n\r\n"
21642 "1")};
21643
21644 const MockWrite kWrites2[] = {
21645 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
21646 "Host: foo.test\r\n"
21647 "Proxy-Connection: keep-alive\r\n\r\n")};
21648
21649 const MockRead kReads2[] = {
21650 MockRead("HTTP/1.1 200 OK\r\n"
21651 "Connection: close\r\n"
21652 "Content-Length: 1\r\n\r\n"
21653 "2")};
21654
21655 StaticSocketDataProvider data1(kReads1, kWrites1);
21656 StaticSocketDataProvider data2(kReads2, kWrites2);
21657 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21658 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21659 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21660
21661 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21662 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
21663 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
21664 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
21665 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
21666 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
21667 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21668 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
21669 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
21670 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21671 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21673
21674 TestCompletionCallback callback;
21675 auto trans1 =
21676 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21677 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21678 EXPECT_THAT(callback.GetResult(rv), IsOk());
21679 std::string response_data1;
21680 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21681 EXPECT_EQ("1", response_data1);
21682 trans1.reset();
21683
21684 auto trans2 =
21685 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21686 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21687 EXPECT_THAT(callback.GetResult(rv), IsOk());
21688 std::string response_data2;
21689 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21690 EXPECT_EQ("2", response_data2);
21691 trans2.reset();
21692}
21693
David Benjaminef2f2a5a2019-07-16 19:21:3121694// Test that SSLConfig changes from SSLConfigService are picked up even when
21695// there are live sockets.
21696TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
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 // Make three requests. Between the second and third, the SSL config will
21706 // change.
21707 HttpRequestInfo request1;
21708 request1.method = "GET";
21709 request1.url = GURL("https://foo.test/1");
21710 request1.traffic_annotation =
21711 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21712
21713 HttpRequestInfo request2;
21714 request2.method = "GET";
21715 request2.url = GURL("https://foo.test/2");
21716 request2.traffic_annotation =
21717 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21718
21719 HttpRequestInfo request3;
21720 request3.method = "GET";
21721 request3.url = GURL("https://foo.test/3");
21722 request3.traffic_annotation =
21723 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21724
21725 const MockWrite kWrites1[] = {
21726 MockWrite("GET /1 HTTP/1.1\r\n"
21727 "Host: foo.test\r\n"
21728 "Connection: keep-alive\r\n\r\n"),
21729 MockWrite("GET /2 HTTP/1.1\r\n"
21730 "Host: foo.test\r\n"
21731 "Connection: keep-alive\r\n\r\n"),
21732 };
21733
21734 const MockRead kReads1[] = {
21735 MockRead("HTTP/1.1 200 OK\r\n"
21736 "Connection: keep-alive\r\n"
21737 "Content-Length: 1\r\n\r\n"
21738 "1"),
21739 MockRead("HTTP/1.1 200 OK\r\n"
21740 "Connection: keep-alive\r\n"
21741 "Content-Length: 1\r\n\r\n"
21742 "2"),
21743 };
21744
21745 // The third request goes on a different socket because the SSL config has
21746 // changed.
21747 const MockWrite kWrites2[] = {
21748 MockWrite("GET /3 HTTP/1.1\r\n"
21749 "Host: foo.test\r\n"
21750 "Connection: keep-alive\r\n\r\n")};
21751
21752 const MockRead kReads2[] = {
21753 MockRead("HTTP/1.1 200 OK\r\n"
21754 "Connection: keep-alive\r\n"
21755 "Content-Length: 1\r\n\r\n"
21756 "3")};
21757
21758 StaticSocketDataProvider data1(kReads1, kWrites1);
21759 StaticSocketDataProvider data2(kReads2, kWrites2);
21760 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21761 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21762
21763 SSLSocketDataProvider ssl1(ASYNC, OK);
21764 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21765 SSLSocketDataProvider ssl2(ASYNC, OK);
21766 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21767 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21768 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21769
21770 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21771
21772 TestCompletionCallback callback;
21773 auto trans1 =
21774 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21775 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21776 EXPECT_THAT(callback.GetResult(rv), IsOk());
21777 std::string response_data1;
21778 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21779 EXPECT_EQ("1", response_data1);
21780 trans1.reset();
21781
21782 auto trans2 =
21783 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21784 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21785 EXPECT_THAT(callback.GetResult(rv), IsOk());
21786 std::string response_data2;
21787 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21788 EXPECT_EQ("2", response_data2);
21789 trans2.reset();
21790
David Benjamin151ec6b2019-08-02 19:38:5221791 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21792 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121793
21794 auto trans3 =
21795 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21796 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21797 EXPECT_THAT(callback.GetResult(rv), IsOk());
21798 std::string response_data3;
21799 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21800 EXPECT_EQ("3", response_data3);
21801 trans3.reset();
21802}
21803
21804TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
David Benjamin151ec6b2019-08-02 19:38:5221805 SSLContextConfig ssl_context_config;
21806 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21807 auto ssl_config_service =
21808 std::make_unique<TestSSLConfigService>(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121809 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21810
21811 session_deps_.ssl_config_service = std::move(ssl_config_service);
21812
21813 HttpRequestInfo request;
21814 request.method = "GET";
21815 request.url = GURL("https://foo.test/1");
21816 request.traffic_annotation =
21817 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21818
21819 // Make a socket which never connects.
21820 StaticSocketDataProvider data({}, {});
21821 session_deps_.socket_factory->AddSocketDataProvider(&data);
21822 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
21823 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21824 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
21825
21826 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21827
21828 TestCompletionCallback callback;
21829 auto trans =
21830 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21831 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21832 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21833
David Benjamin151ec6b2019-08-02 19:38:5221834 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21835 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
David Benjaminef2f2a5a2019-07-16 19:21:3121836
21837 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
21838}
21839
David Benjaminbac8dff2019-08-07 01:30:4121840// Test that HttpNetworkTransaction correctly handles existing sockets when the
21841// server requests a client certificate post-handshake (via a TLS
21842// renegotiation). This is a regression test for https://crbug.com/829184.
21843TEST_F(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
21844 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
21845 TRAFFIC_ANNOTATION_FOR_TESTS);
21846
21847 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
21848 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
21849
21850 std::unique_ptr<FakeClientCertIdentity> identity =
21851 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
21852 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
21853 ASSERT_TRUE(identity);
21854
21855 // This test will make several requests so that, when the client certificate
21856 // request comes in, we have a socket in use, an idle socket, and a socket for
21857 // an unrelated host.
21858 //
21859 // First, two long-lived requests which do not complete until after the client
21860 // certificate request. This arranges for sockets to be in use during the
21861 // request. They should not be interrupted.
21862 HttpRequestInfo request_long_lived;
21863 request_long_lived.method = "GET";
21864 request_long_lived.url = GURL("https://foo.test/long-lived");
21865 request_long_lived.traffic_annotation = kTrafficAnnotation;
21866
21867 HttpRequestInfo request_long_lived_bar;
21868 request_long_lived_bar.method = "GET";
21869 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
21870 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
21871
21872 // Next, make a request that needs client certificates.
21873 HttpRequestInfo request_auth;
21874 request_auth.method = "GET";
21875 request_auth.url = GURL("https://foo.test/auth");
21876 request_auth.traffic_annotation = kTrafficAnnotation;
21877
21878 // Before responding to the challenge, make a request to an unauthenticated
21879 // endpoint. This will result in an idle socket when the client certificate
21880 // challenge is resolved.
21881 HttpRequestInfo request_unauth;
21882 request_unauth.method = "GET";
21883 request_unauth.url = GURL("https://foo.test/unauth");
21884 request_unauth.traffic_annotation = kTrafficAnnotation;
21885
21886 // After all the preceding requests complete, end with two additional requests
21887 // to ensure pre-authentication foo.test sockets are not used and bar.test
21888 // sockets are unaffected.
21889 HttpRequestInfo request_post_auth;
21890 request_post_auth.method = "GET";
21891 request_post_auth.url = GURL("https://foo.test/post-auth");
21892 request_post_auth.traffic_annotation = kTrafficAnnotation;
21893
21894 HttpRequestInfo request_post_auth_bar;
21895 request_post_auth_bar.method = "GET";
21896 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
21897 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
21898
21899 // The sockets for /long-lived and /unauth complete their request but are
21900 // not allocated for /post-auth or /retry because SSL state has since changed.
21901 const MockWrite kLongLivedWrites[] = {
21902 MockWrite(ASYNC, 0,
21903 "GET /long-lived HTTP/1.1\r\n"
21904 "Host: foo.test\r\n"
21905 "Connection: keep-alive\r\n\r\n"),
21906 };
21907 const MockRead kLongLivedReads[] = {
21908 // Pause so /long-lived completes after the client presents client
21909 // certificates.
21910 MockRead(ASYNC, ERR_IO_PENDING, 1),
21911 MockRead(ASYNC, 2,
21912 "HTTP/1.1 200 OK\r\n"
21913 "Connection: keep-alive\r\n"
21914 "Content-Length: 10\r\n\r\n"
21915 "long-lived"),
21916 };
21917 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
21918 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
21919 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
21920 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
21921
21922 // Requests for bar.test should be unaffected by foo.test and get allocated
21923 // a single socket.
21924 const MockWrite kBarWrites[] = {
21925 MockWrite(ASYNC, 0,
21926 "GET /long-lived HTTP/1.1\r\n"
21927 "Host: bar.test\r\n"
21928 "Connection: keep-alive\r\n\r\n"),
21929 MockWrite(ASYNC, 3,
21930 "GET /post-auth HTTP/1.1\r\n"
21931 "Host: bar.test\r\n"
21932 "Connection: keep-alive\r\n\r\n"),
21933 };
21934 const MockRead kBarReads[] = {
21935 // Pause on /long-lived so it completes after foo.test's authentication.
21936 MockRead(ASYNC, ERR_IO_PENDING, 1),
21937 MockRead(ASYNC, 2,
21938 "HTTP/1.1 200 OK\r\n"
21939 "Connection: keep-alive\r\n"
21940 "Content-Length: 10\r\n\r\n"
21941 "long-lived"),
21942 MockRead(ASYNC, 4,
21943 "HTTP/1.1 200 OK\r\n"
21944 "Connection: keep-alive\r\n"
21945 "Content-Length: 9\r\n\r\n"
21946 "post-auth"),
21947 };
21948 SequencedSocketData data_bar(kBarReads, kBarWrites);
21949 SSLSocketDataProvider ssl_bar(ASYNC, OK);
21950 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
21951 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
21952
21953 // Requesting /auth results in a post-handshake client certificate challenge.
21954 const MockWrite kAuthWrites[] = {
21955 MockWrite(ASYNC, 0,
21956 "GET /auth HTTP/1.1\r\n"
21957 "Host: foo.test\r\n"
21958 "Connection: keep-alive\r\n\r\n"),
21959 };
21960 const MockRead kAuthReads[] = {
21961 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
21962 };
21963 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
21964 SSLSocketDataProvider ssl_auth(ASYNC, OK);
21965 ssl_auth.cert_request_info = cert_request_info.get();
21966 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
21967 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
21968
21969 // Requesting /unauth completes.
21970 const MockWrite kUnauthWrites[] = {
21971 MockWrite(ASYNC, 0,
21972 "GET /unauth HTTP/1.1\r\n"
21973 "Host: foo.test\r\n"
21974 "Connection: keep-alive\r\n\r\n"),
21975 };
21976 const MockRead kUnauthReads[] = {
21977 MockRead(ASYNC, 1,
21978 "HTTP/1.1 200 OK\r\n"
21979 "Connection: keep-alive\r\n"
21980 "Content-Length: 6\r\n\r\n"
21981 "unauth"),
21982 };
21983 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
21984 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
21985 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
21986 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
21987
21988 // When the client certificate is selected, /auth is retried on a new
21989 // connection. In particular, it should not be retried on |data_unauth|,
21990 // which would not honor the new client certificate configuration.
21991 const MockWrite kRetryWrites[] = {
21992 MockWrite(ASYNC, 0,
21993 "GET /auth HTTP/1.1\r\n"
21994 "Host: foo.test\r\n"
21995 "Connection: keep-alive\r\n\r\n"),
21996 };
21997 const MockRead kRetryReads[] = {
21998 MockRead(ASYNC, 1,
21999 "HTTP/1.1 200 OK\r\n"
22000 // Close the connection so we test that /post-auth is not
22001 // allocated to |data_unauth| or |data_long_lived|.
22002 "Connection: close\r\n"
22003 "Content-Length: 4\r\n\r\n"
22004 "auth"),
22005 };
22006 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
22007 SSLSocketDataProvider ssl_retry(ASYNC, OK);
22008 ssl_retry.expected_send_client_cert = true;
22009 ssl_retry.expected_client_cert = identity->certificate();
22010 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
22011 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
22012
22013 // /post-auth gets its own socket.
22014 const MockWrite kPostAuthWrites[] = {
22015 MockWrite(ASYNC, 0,
22016 "GET /post-auth HTTP/1.1\r\n"
22017 "Host: foo.test\r\n"
22018 "Connection: keep-alive\r\n\r\n"),
22019 };
22020 const MockRead kPostAuthReads[] = {
22021 MockRead(ASYNC, 1,
22022 "HTTP/1.1 200 OK\r\n"
22023 "Connection: keep-alive\r\n"
22024 "Content-Length: 9\r\n\r\n"
22025 "post-auth"),
22026 };
22027 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
22028 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
22029 ssl_post_auth.expected_send_client_cert = true;
22030 ssl_post_auth.expected_client_cert = identity->certificate();
22031 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
22032 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
22033
22034 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
22035
22036 // Start the two long-lived requests.
22037 TestCompletionCallback callback_long_lived;
22038 auto trans_long_lived =
22039 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22040 int rv = trans_long_lived->Start(
22041 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
22042 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22043 data_long_lived.RunUntilPaused();
22044
22045 TestCompletionCallback callback_long_lived_bar;
22046 auto trans_long_lived_bar =
22047 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22048 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
22049 callback_long_lived_bar.callback(),
22050 NetLogWithSource());
22051 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
22052 data_bar.RunUntilPaused();
22053
22054 // Request /auth. This gives a client certificate challenge.
22055 TestCompletionCallback callback_auth;
22056 auto trans_auth =
22057 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22058 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
22059 NetLogWithSource());
22060 EXPECT_THAT(callback_auth.GetResult(rv),
22061 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
22062
22063 // Make an unauthenticated request. This completes.
22064 TestCompletionCallback callback_unauth;
22065 auto trans_unauth =
22066 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22067 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
22068 NetLogWithSource());
22069 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
22070 std::string response_unauth;
22071 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
22072 EXPECT_EQ("unauth", response_unauth);
22073 trans_unauth.reset();
22074
22075 // Complete the authenticated request.
22076 rv = trans_auth->RestartWithCertificate(identity->certificate(),
22077 identity->ssl_private_key(),
22078 callback_auth.callback());
22079 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
22080 std::string response_auth;
22081 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
22082 EXPECT_EQ("auth", response_auth);
22083 trans_auth.reset();
22084
22085 // Complete the long-lived requests.
22086 data_long_lived.Resume();
22087 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
22088 std::string response_long_lived;
22089 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
22090 IsOk());
22091 EXPECT_EQ("long-lived", response_long_lived);
22092 trans_long_lived.reset();
22093
22094 data_bar.Resume();
22095 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
22096 std::string response_long_lived_bar;
22097 EXPECT_THAT(
22098 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
22099 IsOk());
22100 EXPECT_EQ("long-lived", response_long_lived_bar);
22101 trans_long_lived_bar.reset();
22102
22103 // Run the post-authentication requests.
22104 TestCompletionCallback callback_post_auth;
22105 auto trans_post_auth =
22106 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22107 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
22108 NetLogWithSource());
22109 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
22110 std::string response_post_auth;
22111 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
22112 IsOk());
22113 EXPECT_EQ("post-auth", response_post_auth);
22114 trans_post_auth.reset();
22115
22116 TestCompletionCallback callback_post_auth_bar;
22117 auto trans_post_auth_bar =
22118 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22119 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
22120 callback_post_auth_bar.callback(),
22121 NetLogWithSource());
22122 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
22123 std::string response_post_auth_bar;
22124 EXPECT_THAT(
22125 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
22126 IsOk());
22127 EXPECT_EQ("post-auth", response_post_auth_bar);
22128 trans_post_auth_bar.reset();
22129}
22130
[email protected]89ceba9a2009-03-21 03:46:0622131} // namespace net