blob: b1c0dc552b1262a17ad9cbef642c9c649419b789 [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 Menkeecfecfc72019-02-05 19:15:2833#include "base/test/scoped_task_environment.h"
Douglas Creager134b52e2018-11-09 18:00:1434#include "base/test/simple_test_clock.h"
35#include "base/test/simple_test_tick_clock.h"
[email protected]f36a8132011-09-02 18:36:3336#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3537#include "base/threading/thread_task_runner_handle.h"
Matt Menke5062be22019-05-01 17:50:2438#include "build/build_config.h"
[email protected]277d5942010-08-11 21:02:3539#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0740#include "net/base/chunked_upload_data_stream.h"
Bence Békya25e3f72018-02-13 21:13:3941#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0742#include "net/base/elements_upload_data_stream.h"
Eric Orthf4db66a2019-02-19 21:35:3343#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3744#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2545#include "net/base/load_timing_info.h"
46#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2447#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5948#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1549#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4050#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3151#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5252#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1553#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0654#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2155#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0856#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1157#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5358#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2459#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1260#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0061#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2962#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1963#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5764#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5265#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5666#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0467#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2468#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1369#include "net/http/http_response_info.h"
[email protected]17291a022011-10-10 07:32:5370#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5771#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3872#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1973#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0774#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0075#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1976#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5177#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4678#include "net/log/test_net_log_entry.h"
79#include "net/log/test_net_log_util.h"
Lily Houghton582d4622018-01-22 22:43:4080#include "net/proxy_resolution/mock_proxy_resolver.h"
81#include "net/proxy_resolution/proxy_config_service_fixed.h"
82#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0383#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4084#include "net/proxy_resolution/proxy_resolver.h"
85#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4486#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1587#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0388#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3689#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4790#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0291#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0792#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0493#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4494#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1295#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4496#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:5897#include "net/spdy/spdy_session.h"
98#include "net/spdy/spdy_session_pool.h"
99#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04100#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57101#include "net/ssl/ssl_cert_request_info.h"
[email protected]e86839fd2013-08-14 18:29:03102#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57103#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54104#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:11105#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01106#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43107#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:01108#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14109#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23110#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00111#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44112#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06113#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18114#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52115#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15116#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27117#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52118
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37119#if defined(NTLM_PORTABLE)
120#include "base/base64.h"
121#include "net/ntlm/ntlm_test_data.h"
122#endif
123
Douglas Creager3cb042052018-11-06 23:08:52124#if BUILDFLAG(ENABLE_REPORTING)
125#include "net/network_error_logging/network_error_logging_service.h"
126#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14127#include "net/reporting/reporting_cache.h"
128#include "net/reporting/reporting_client.h"
129#include "net/reporting/reporting_header_parser.h"
130#include "net/reporting/reporting_service.h"
131#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52132#endif // BUILDFLAG(ENABLE_REPORTING)
133
robpercival214763f2016-07-01 23:27:01134using net::test::IsError;
135using net::test::IsOk;
136
[email protected]ad65a3e2013-12-25 18:18:01137using base::ASCIIToUTF16;
138
David Benjamin3b94b0f2019-04-25 23:07:52139using testing::AnyOf;
140
initial.commit586acc5fe2008-07-26 22:42:52141//-----------------------------------------------------------------------------
142
ttuttle859dc7a2015-04-23 19:42:29143namespace net {
144
[email protected]13c8a092010-07-29 06:15:44145namespace {
146
[email protected]42cba2fb2013-03-29 19:58:57147const base::string16 kBar(ASCIIToUTF16("bar"));
148const base::string16 kBar2(ASCIIToUTF16("bar2"));
149const base::string16 kBar3(ASCIIToUTF16("bar3"));
150const base::string16 kBaz(ASCIIToUTF16("baz"));
151const base::string16 kFirst(ASCIIToUTF16("first"));
152const base::string16 kFoo(ASCIIToUTF16("foo"));
153const base::string16 kFoo2(ASCIIToUTF16("foo2"));
154const base::string16 kFoo3(ASCIIToUTF16("foo3"));
155const base::string16 kFou(ASCIIToUTF16("fou"));
156const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57157const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44158
bnc2df4b522016-07-08 18:17:43159const char kAlternativeServiceHttpHeader[] =
160 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
161
ttuttle859dc7a2015-04-23 19:42:29162int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40163 return session
164 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
165 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29166 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02167}
168
ttuttle859dc7a2015-04-23 19:42:29169bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40170 return session
171 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
172 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29173 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52174}
175
[email protected]f3da152d2012-06-02 01:00:57176// Takes in a Value created from a NetLogHttpResponseParameter, and returns
177// a JSONified list of headers as a single string. Uses single quotes instead
178// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27179bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57180 if (!params)
181 return false;
[email protected]ea5ef4c2013-06-13 22:50:27182 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57183 if (!params->GetList("headers", &header_list))
184 return false;
185 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34186 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28187 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57188 return true;
189}
190
[email protected]029c83b62013-01-24 05:28:20191// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
192// used.
ttuttle859dc7a2015-04-23 19:42:29193void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20194 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19195 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25196
[email protected]029c83b62013-01-24 05:28:20197 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
198 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
199
ttuttle859dc7a2015-04-23 19:42:29200 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20201 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25202
203 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25204
[email protected]3b23a222013-05-15 21:33:25205 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25206 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
207 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25208 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25209}
210
[email protected]029c83b62013-01-24 05:28:20211// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
212// used.
ttuttle859dc7a2015-04-23 19:42:29213void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25214 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20215 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19216 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20217
218 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
219 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
220
ttuttle859dc7a2015-04-23 19:42:29221 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
222 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20223 EXPECT_LE(load_timing_info.connect_timing.connect_end,
224 load_timing_info.send_start);
225
226 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20227
[email protected]3b23a222013-05-15 21:33:25228 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20229 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
230 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25231 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20232}
233
234// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
235// used.
ttuttle859dc7a2015-04-23 19:42:29236void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20237 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19238 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20239
ttuttle859dc7a2015-04-23 19:42:29240 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20241
242 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
243 EXPECT_LE(load_timing_info.proxy_resolve_start,
244 load_timing_info.proxy_resolve_end);
245 EXPECT_LE(load_timing_info.proxy_resolve_end,
246 load_timing_info.send_start);
247 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20248
[email protected]3b23a222013-05-15 21:33:25249 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20250 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
251 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25252 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20253}
254
255// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
256// used.
ttuttle859dc7a2015-04-23 19:42:29257void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20258 int connect_timing_flags) {
259 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19260 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20261
262 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
263 EXPECT_LE(load_timing_info.proxy_resolve_start,
264 load_timing_info.proxy_resolve_end);
265 EXPECT_LE(load_timing_info.proxy_resolve_end,
266 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29267 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
268 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20269 EXPECT_LE(load_timing_info.connect_timing.connect_end,
270 load_timing_info.send_start);
271
272 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20273
[email protected]3b23a222013-05-15 21:33:25274 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20275 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
276 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25277 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25278}
279
Matt Menke2436b2f2018-12-11 18:07:11280// ProxyResolver that records URLs passed to it, and that can be told what
281// result to return.
282class CapturingProxyResolver : public ProxyResolver {
283 public:
284 CapturingProxyResolver()
285 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
286 ~CapturingProxyResolver() override = default;
287
288 int GetProxyForURL(const GURL& url,
289 ProxyInfo* results,
290 CompletionOnceCallback callback,
291 std::unique_ptr<Request>* request,
292 const NetLogWithSource& net_log) override {
293 results->UseProxyServer(proxy_server_);
294 resolved_.push_back(url);
295 return OK;
296 }
297
298 // Sets whether the resolver should use direct connections, instead of a
299 // proxy.
300 void set_proxy_server(ProxyServer proxy_server) {
301 proxy_server_ = proxy_server;
302 }
303
304 const std::vector<GURL>& resolved() const { return resolved_; }
305
306 private:
307 std::vector<GURL> resolved_;
308
309 ProxyServer proxy_server_;
310
311 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
312};
313
314class CapturingProxyResolverFactory : public ProxyResolverFactory {
315 public:
316 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
317 : ProxyResolverFactory(false), resolver_(resolver) {}
318
319 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
320 std::unique_ptr<ProxyResolver>* resolver,
321 CompletionOnceCallback callback,
322 std::unique_ptr<Request>* request) override {
323 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
324 return OK;
325 }
326
327 private:
328 ProxyResolver* resolver_;
329};
330
danakj1fd259a02016-04-16 03:17:09331std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42332 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34333 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14334}
335
xunjieli96f2a402017-06-05 17:24:27336class FailingProxyResolverFactory : public ProxyResolverFactory {
337 public:
338 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
339
340 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42341 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
342 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17343 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42344 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27345 return ERR_PAC_SCRIPT_FAILED;
346 }
347};
348
David Benjamin5cb91132018-04-06 05:54:49349class TestSSLConfigService : public SSLConfigService {
350 public:
351 explicit TestSSLConfigService(const SSLConfig& config) : config_(config) {}
Ryan Sleevib8449e02018-07-15 04:31:07352 ~TestSSLConfigService() override = default;
David Benjamin5cb91132018-04-06 05:54:49353
354 void GetSSLConfig(SSLConfig* config) override { *config = config_; }
355
Nick Harper89bc7212018-07-31 19:07:57356 bool CanShareConnectionWithClientCerts(
357 const std::string& hostname) const override {
358 return false;
359 }
360
David Benjamin5cb91132018-04-06 05:54:49361 private:
David Benjamin5cb91132018-04-06 05:54:49362 SSLConfig config_;
363};
364
[email protected]448d4ca52012-03-04 04:12:23365} // namespace
366
Bence Béky98447b12018-05-08 03:14:01367class HttpNetworkTransactionTest : public PlatformTest,
368 public WithScopedTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03369 public:
bncd16676a2016-07-20 16:23:01370 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03371 // Important to restore the per-pool limit first, since the pool limit must
372 // always be greater than group limit, and the tests reduce both limits.
373 ClientSocketPoolManager::set_max_sockets_per_pool(
374 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
375 ClientSocketPoolManager::set_max_sockets_per_group(
376 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
377 }
378
[email protected]e3ceb682011-06-28 23:55:46379 protected:
[email protected]23e482282013-06-14 16:08:02380 HttpNetworkTransactionTest()
Andrew Comminos517a92c2019-01-14 17:49:56381 : WithScopedTaskEnvironment(
382 base::test::ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME,
383 base::test::ScopedTaskEnvironment::NowSource::
384 MAIN_THREAD_MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36385 dummy_connect_job_params_(
386 nullptr /* client_socket_factory */,
387 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40388 nullptr /* http_auth_cache */,
389 nullptr /* http_auth_handler_factory */,
390 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13391 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40392 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36393 nullptr /* proxy_delegate */,
394 nullptr /* http_user_agent_settings */,
395 SSLClientSocketContext(),
396 SSLClientSocketContext(),
397 nullptr /* socket_performance_watcher_factory */,
398 nullptr /* network_quality_estimator */,
399 nullptr /* net_log */,
400 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56401 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15402 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03403 HttpNetworkSession::NORMAL_SOCKET_POOL)),
404 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
405 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28406 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03407 }
[email protected]bb88e1d32013-05-03 23:11:07408
[email protected]e3ceb682011-06-28 23:55:46409 struct SimpleGetHelperResult {
410 int rv;
411 std::string status_line;
412 std::string response_data;
sclittlefb249892015-09-10 21:33:22413 int64_t total_received_bytes;
414 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25415 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47416 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59417 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46418 };
419
dcheng67be2b1f2014-10-27 21:47:29420 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50421 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55422 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56423 // Set an initial delay to ensure that the first call to TimeTicks::Now()
424 // before incrementing the counter does not return a null value.
425 FastForwardBy(TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54426 }
427
dcheng67be2b1f2014-10-27 21:47:29428 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50429 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55430 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09431 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55432 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09433 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50434 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55435 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09436 }
437
Andrew Comminos1f2ff1cc2018-12-14 05:22:38438 void Check100ResponseTiming(bool use_spdy);
439
[email protected]202965992011-12-07 23:04:51440 // Either |write_failure| specifies a write failure or |read_failure|
441 // specifies a read failure when using a reused socket. In either case, the
442 // failure should cause the network transaction to resend the request, and the
443 // other argument should be NULL.
444 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
445 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52446
[email protected]a34f61ee2014-03-18 20:59:49447 // Either |write_failure| specifies a write failure or |read_failure|
448 // specifies a read failure when using a reused socket. In either case, the
449 // failure should cause the network transaction to resend the request, and the
450 // other argument should be NULL.
451 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10452 const MockRead* read_failure,
453 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49454
Ryan Sleevib8d7ea02018-05-07 20:01:01455 SimpleGetHelperResult SimpleGetHelperForData(
456 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15457 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52458
[email protected]ff007e162009-05-23 09:13:15459 HttpRequestInfo request;
460 request.method = "GET";
bncce36dca22015-04-21 22:11:23461 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:10462 request.traffic_annotation =
463 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52464
vishal.b62985ca92015-04-17 08:45:51465 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07466 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09467 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16468 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27469
Ryan Sleevib8d7ea02018-05-07 20:01:01470 for (auto* provider : providers) {
471 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29472 }
initial.commit586acc5fe2008-07-26 22:42:52473
[email protected]49639fa2011-12-20 23:22:41474 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52475
eroman24bc6a12015-05-06 19:55:48476 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16477 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01478 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52479
[email protected]ff007e162009-05-23 09:13:15480 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16481 out.total_received_bytes = trans.GetTotalReceivedBytes();
482 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25483
484 // Even in the failure cases that use this function, connections are always
485 // successfully established before the error.
bnc691fda62016-08-12 00:43:16486 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25487 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
488
[email protected]ff007e162009-05-23 09:13:15489 if (out.rv != OK)
490 return out;
491
bnc691fda62016-08-12 00:43:16492 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50493 // Can't use ASSERT_* inside helper functions like this, so
494 // return an error.
wezca1070932016-05-26 20:30:52495 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50496 out.rv = ERR_UNEXPECTED;
497 return out;
498 }
[email protected]ff007e162009-05-23 09:13:15499 out.status_line = response->headers->GetStatusLine();
500
Tsuyoshi Horo01faed62019-02-20 22:11:37501 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
502 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19503
ttuttled9dbc652015-09-29 20:00:59504 bool got_endpoint =
bnc691fda62016-08-12 00:43:16505 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59506 EXPECT_EQ(got_endpoint,
507 out.remote_endpoint_after_start.address().size() > 0);
508
bnc691fda62016-08-12 00:43:16509 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01510 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40511
mmenke43758e62015-05-04 21:09:46512 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40513 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39514 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00515 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
516 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39517 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00518 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
519 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15520
[email protected]f3da152d2012-06-02 01:00:57521 std::string line;
522 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
523 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
524
[email protected]79e1fd62013-06-20 06:50:04525 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:16526 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:04527 std::string value;
528 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23529 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04530 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
531 EXPECT_EQ("keep-alive", value);
532
533 std::string response_headers;
534 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23535 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04536 response_headers);
[email protected]3deb9a52010-11-11 00:24:40537
bnc691fda62016-08-12 00:43:16538 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22539 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16540 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22541
bnc691fda62016-08-12 00:43:16542 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47543 return out;
[email protected]ff007e162009-05-23 09:13:15544 }
initial.commit586acc5fe2008-07-26 22:42:52545
Ryan Sleevib8d7ea02018-05-07 20:01:01546 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22547 MockWrite data_writes[] = {
548 MockWrite("GET / HTTP/1.1\r\n"
549 "Host: www.example.org\r\n"
550 "Connection: keep-alive\r\n\r\n"),
551 };
[email protected]5a60c8b2011-10-19 20:14:29552
Ryan Sleevib8d7ea02018-05-07 20:01:01553 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22554 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01555 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22556
Ryan Sleevib8d7ea02018-05-07 20:01:01557 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22558 return out;
[email protected]b8015c42013-12-24 15:18:19559 }
560
bnc032658ba2016-09-26 18:17:15561 void AddSSLSocketData() {
562 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49563 ssl_.ssl_info.cert =
564 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
565 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15566 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
567 }
568
[email protected]ff007e162009-05-23 09:13:15569 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
570 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52571
[email protected]ff007e162009-05-23 09:13:15572 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07573
[email protected]bb88e1d32013-05-03 23:11:07574 void CheckErrorIsPassedBack(int error, IoMode mode);
575
Matt Menked6fd2a52019-03-20 06:14:36576 const CommonConnectJobParams dummy_connect_job_params_;
577
Douglas Creager134b52e2018-11-09 18:00:14578 // These clocks are defined here, even though they're only used in the
579 // Reporting tests below, since they need to be destroyed after
580 // |session_deps_|.
581 base::SimpleTestClock clock_;
582 base::SimpleTestTickClock tick_clock_;
583
[email protected]4bd46222013-05-14 19:32:23584 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07585 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15586 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03587
588 // Original socket limits. Some tests set these. Safest to always restore
589 // them once each test has been run.
590 int old_max_group_sockets_;
591 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15592};
[email protected]231d5a32008-09-13 00:45:27593
[email protected]448d4ca52012-03-04 04:12:23594namespace {
595
ryansturm49a8cb12016-06-15 16:51:09596class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27597 public:
ryansturm49a8cb12016-06-15 16:51:09598 BeforeHeadersSentHandler()
599 : observed_before_headers_sent_with_proxy_(false),
600 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27601
ryansturm49a8cb12016-06-15 16:51:09602 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
603 HttpRequestHeaders* request_headers) {
604 observed_before_headers_sent_ = true;
605 if (!proxy_info.is_http() && !proxy_info.is_https() &&
606 !proxy_info.is_quic()) {
607 return;
608 }
609 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27610 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
611 }
612
ryansturm49a8cb12016-06-15 16:51:09613 bool observed_before_headers_sent_with_proxy() const {
614 return observed_before_headers_sent_with_proxy_;
615 }
616
617 bool observed_before_headers_sent() const {
618 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27619 }
620
621 std::string observed_proxy_server_uri() const {
622 return observed_proxy_server_uri_;
623 }
624
625 private:
ryansturm49a8cb12016-06-15 16:51:09626 bool observed_before_headers_sent_with_proxy_;
627 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27628 std::string observed_proxy_server_uri_;
629
ryansturm49a8cb12016-06-15 16:51:09630 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27631};
632
[email protected]15a5ccf82008-10-23 19:57:43633// Fill |str| with a long header list that consumes >= |size| bytes.
634void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51635 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19636 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
637 const int sizeof_row = strlen(row);
638 const int num_rows = static_cast<int>(
639 ceil(static_cast<float>(size) / sizeof_row));
640 const int sizeof_data = num_rows * sizeof_row;
641 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43642 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51643
[email protected]4ddaf2502008-10-23 18:26:19644 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43645 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19646}
647
thakis84dff942015-07-28 20:47:38648#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09649uint64_t MockGetMSTime() {
650 // Tue, 23 May 2017 20:13:07 +0000
651 return 131400439870000000;
652}
653
[email protected]385a4672009-03-11 22:21:29654// Alternative functions that eliminate randomness and dependency on the local
655// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37656void MockGenerateRandom(uint8_t* output, size_t n) {
657 // This is set to 0xaa because the client challenge for testing in
658 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
659 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29660}
661
[email protected]fe2bc6a2009-03-23 16:52:20662std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37663 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29664}
thakis84dff942015-07-28 20:47:38665#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29666
Matt Menked6fd2a52019-03-20 06:14:36667class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31668 public:
Matt Menked6fd2a52019-03-20 06:14:36669 explicit CaptureGroupIdTransportSocketPool(
670 const CommonConnectJobParams* common_connect_job_params)
671 : TransportClientSocketPool(0,
672 0,
673 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36674 ProxyServer::Direct(),
675 false /* is_for_websockets */,
Matt Menked6fd2a52019-03-20 06:14:36676 common_connect_job_params,
677 nullptr /* ssl_config_service */) {}
[email protected]e60e47a2010-07-14 03:37:18678
Matt Menkef6edce752019-03-19 17:21:56679 const ClientSocketPool::GroupId& last_group_id_received() const {
680 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49681 }
682
Tarun Bansal162eabe52018-01-20 01:16:39683 bool socket_requested() const { return socket_requested_; }
684
Matt Menke28ac03e2019-02-25 22:25:50685 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56686 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03687 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28688 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50689 RequestPriority priority,
690 const SocketTag& socket_tag,
691 ClientSocketPool::RespectLimits respect_limits,
692 ClientSocketHandle* handle,
693 CompletionOnceCallback callback,
694 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
695 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56696 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39697 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31698 return ERR_IO_PENDING;
699 }
Matt Menkef6edce752019-03-19 17:21:56700 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21701 ClientSocketHandle* handle,
702 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56703 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09704 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24705 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57706 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56707 void CloseIdleSocketsInGroup(
708 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57709 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56710 size_t IdleSocketCountInGroup(
711 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31712 return 0;
713 }
Matt Menkef6edce752019-03-19 17:21:56714 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57715 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31716 return LOAD_STATE_IDLE;
717 }
[email protected]d80a4322009-08-14 07:07:49718
719 private:
Matt Menkef6edce752019-03-19 17:21:56720 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39721 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31722};
723
[email protected]231d5a32008-09-13 00:45:27724//-----------------------------------------------------------------------------
725
[email protected]79cb5c12011-09-12 13:12:04726// Helper functions for validating that AuthChallengeInfo's are correctly
727// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58728bool CheckBasicServerAuth(
729 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04730 if (!auth_challenge)
731 return false;
732 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43733 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04734 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19735 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04736 return true;
737}
738
David Benjamin2eb827f2019-04-29 18:31:04739bool CheckBasicSecureServerAuth(
740 const base::Optional<AuthChallengeInfo>& auth_challenge) {
741 if (!auth_challenge)
742 return false;
743 EXPECT_FALSE(auth_challenge->is_proxy);
744 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
745 EXPECT_EQ("MyRealm1", auth_challenge->realm);
746 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
747 return true;
748}
749
Emily Starkf2c9bbd2019-04-09 17:08:58750bool CheckBasicProxyAuth(
751 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04752 if (!auth_challenge)
753 return false;
754 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43755 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
756 EXPECT_EQ("MyRealm1", auth_challenge->realm);
757 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
758 return true;
759}
760
Emily Starkf2c9bbd2019-04-09 17:08:58761bool CheckBasicSecureProxyAuth(
762 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43763 if (!auth_challenge)
764 return false;
765 EXPECT_TRUE(auth_challenge->is_proxy);
766 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04767 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19768 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04769 return true;
770}
771
Emily Starkf2c9bbd2019-04-09 17:08:58772bool CheckDigestServerAuth(
773 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04774 if (!auth_challenge)
775 return false;
776 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43777 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04778 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19779 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04780 return true;
781}
782
thakis84dff942015-07-28 20:47:38783#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58784bool CheckNTLMServerAuth(
785 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04786 if (!auth_challenge)
787 return false;
788 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55789 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04790 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19791 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04792 return true;
793}
David Benjamin5cb91132018-04-06 05:54:49794
Emily Starkf2c9bbd2019-04-09 17:08:58795bool CheckNTLMProxyAuth(
796 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49797 if (!auth_challenge)
798 return false;
799 EXPECT_TRUE(auth_challenge->is_proxy);
800 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
801 EXPECT_EQ(std::string(), auth_challenge->realm);
802 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
803 return true;
804}
thakis84dff942015-07-28 20:47:38805#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04806
[email protected]448d4ca52012-03-04 04:12:23807} // namespace
808
bncd16676a2016-07-20 16:23:01809TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16811 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27812}
813
bncd16676a2016-07-20 16:23:01814TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27815 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35816 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
817 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06818 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27819 };
Ryan Sleevib8d7ea02018-05-07 20:01:01820 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01821 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27822 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
823 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01824 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22825 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47826 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59827
828 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27829}
830
831// Response with no status line.
bncd16676a2016-07-20 16:23:01832TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27833 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35834 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06835 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27836 };
Ryan Sleevib8d7ea02018-05-07 20:01:01837 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41838 EXPECT_THAT(out.rv, IsOk());
839 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
840 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01841 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41842 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27843}
844
mmenkea7da6da2016-09-01 21:56:52845// Response with no status line, and a weird port. Should fail by default.
846TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
847 MockRead data_reads[] = {
848 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
849 };
850
Ryan Sleevib8d7ea02018-05-07 20:01:01851 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52852 session_deps_.socket_factory->AddSocketDataProvider(&data);
853
854 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
855
krasinc06a72a2016-12-21 03:42:46856 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58857 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19858 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52859
mmenkea7da6da2016-09-01 21:56:52860 request.method = "GET";
861 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e2018-02-07 07:41:10862 request.traffic_annotation =
863 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
864
mmenkea7da6da2016-09-01 21:56:52865 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20866 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52867 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
868}
869
Shivani Sharmafdcaefd2017-11-02 00:12:26870// Tests that request info can be destroyed after the headers phase is complete.
871TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
872 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
873 auto trans =
874 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
875
876 MockRead data_reads[] = {
877 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
878 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
879 };
Ryan Sleevib8d7ea02018-05-07 20:01:01880 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26881 session_deps_.socket_factory->AddSocketDataProvider(&data);
882
883 TestCompletionCallback callback;
884
885 {
886 auto request = std::make_unique<HttpRequestInfo>();
887 request->method = "GET";
888 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:10889 request->traffic_annotation =
890 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26891
892 int rv =
893 trans->Start(request.get(), callback.callback(), NetLogWithSource());
894
895 EXPECT_THAT(callback.GetResult(rv), IsOk());
896 } // Let request info be destroyed.
897
898 trans.reset();
899}
900
mmenkea7da6da2016-09-01 21:56:52901// Response with no status line, and a weird port. Option to allow weird ports
902// enabled.
903TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPortAllowed) {
904 MockRead data_reads[] = {
905 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
906 };
907
Ryan Sleevib8d7ea02018-05-07 20:01:01908 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52909 session_deps_.socket_factory->AddSocketDataProvider(&data);
910 session_deps_.http_09_on_non_default_ports_enabled = true;
911 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
912
krasinc06a72a2016-12-21 03:42:46913 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58914 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19915 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52916
mmenkea7da6da2016-09-01 21:56:52917 request.method = "GET";
918 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e2018-02-07 07:41:10919 request.traffic_annotation =
920 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
921
mmenkea7da6da2016-09-01 21:56:52922 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20923 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52924 EXPECT_THAT(callback.GetResult(rv), IsOk());
925
926 const HttpResponseInfo* info = trans->GetResponseInfo();
927 ASSERT_TRUE(info->headers);
928 EXPECT_EQ("HTTP/0.9 200 OK", info->headers->GetStatusLine());
929
930 // Don't bother to read the body - that's verified elsewhere, important thing
931 // is that the option to allow HTTP/0.9 on non-default ports is respected.
932}
933
[email protected]231d5a32008-09-13 00:45:27934// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01935TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27936 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35937 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[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);
robpercival214763f2016-07-01 23:27:01941 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27942 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
943 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01944 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22945 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27946}
947
948// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01949TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27950 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35951 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06952 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27953 };
Ryan Sleevib8d7ea02018-05-07 20:01:01954 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01955 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27956 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
957 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01958 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22959 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27960}
961
962// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01963TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27964 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35965 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06966 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27967 };
Ryan Sleevib8d7ea02018-05-07 20:01:01968 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41969 EXPECT_THAT(out.rv, IsOk());
970 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
971 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01972 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41973 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27974}
975
976// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01977TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27978 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35979 MockRead("\n"),
980 MockRead("\n"),
981 MockRead("Q"),
982 MockRead("J"),
983 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06984 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27985 };
Ryan Sleevib8d7ea02018-05-07 20:01:01986 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01987 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27988 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
989 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01990 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22991 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27992}
993
994// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01995TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27996 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35997 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06998 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27999 };
Ryan Sleevib8d7ea02018-05-07 20:01:011000 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411001 EXPECT_THAT(out.rv, IsOk());
1002 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1003 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011004 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411005 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:521006}
1007
[email protected]f9d44aa2008-09-23 23:57:171008// Simulate a 204 response, lacking a Content-Length header, sent over a
1009// persistent connection. The response should still terminate since a 204
1010// cannot have a response body.
bncd16676a2016-07-20 16:23:011011TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:191012 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:171013 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351014 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:191015 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:061016 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:171017 };
Ryan Sleevib8d7ea02018-05-07 20:01:011018 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011019 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:171020 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
1021 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011022 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221023 int64_t response_size = reads_size - strlen(junk);
1024 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:171025}
1026
[email protected]0877e3d2009-10-17 22:29:571027// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:011028TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:191029 std::string final_chunk = "0\r\n\r\n";
1030 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1031 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:571032 MockRead data_reads[] = {
1033 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1034 MockRead("5\r\nHello\r\n"),
1035 MockRead("1\r\n"),
1036 MockRead(" \r\n"),
1037 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:191038 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:061039 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:571040 };
Ryan Sleevib8d7ea02018-05-07 20:01:011041 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011042 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:571043 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1044 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011045 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221046 int64_t response_size = reads_size - extra_data.size();
1047 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:571048}
1049
[email protected]9fe44f52010-09-23 18:36:001050// Next tests deal with http://crbug.com/56344.
1051
bncd16676a2016-07-20 16:23:011052TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001053 MultipleContentLengthHeadersNoTransferEncoding) {
1054 MockRead data_reads[] = {
1055 MockRead("HTTP/1.1 200 OK\r\n"),
1056 MockRead("Content-Length: 10\r\n"),
1057 MockRead("Content-Length: 5\r\n\r\n"),
1058 };
Ryan Sleevib8d7ea02018-05-07 20:01:011059 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011060 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001061}
1062
bncd16676a2016-07-20 16:23:011063TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041064 DuplicateContentLengthHeadersNoTransferEncoding) {
1065 MockRead data_reads[] = {
1066 MockRead("HTTP/1.1 200 OK\r\n"),
1067 MockRead("Content-Length: 5\r\n"),
1068 MockRead("Content-Length: 5\r\n\r\n"),
1069 MockRead("Hello"),
1070 };
Ryan Sleevib8d7ea02018-05-07 20:01:011071 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011072 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041073 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1074 EXPECT_EQ("Hello", out.response_data);
1075}
1076
bncd16676a2016-07-20 16:23:011077TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041078 ComplexContentLengthHeadersNoTransferEncoding) {
1079 // More than 2 dupes.
1080 {
1081 MockRead data_reads[] = {
1082 MockRead("HTTP/1.1 200 OK\r\n"),
1083 MockRead("Content-Length: 5\r\n"),
1084 MockRead("Content-Length: 5\r\n"),
1085 MockRead("Content-Length: 5\r\n\r\n"),
1086 MockRead("Hello"),
1087 };
Ryan Sleevib8d7ea02018-05-07 20:01:011088 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011089 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041090 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1091 EXPECT_EQ("Hello", out.response_data);
1092 }
1093 // HTTP/1.0
1094 {
1095 MockRead data_reads[] = {
1096 MockRead("HTTP/1.0 200 OK\r\n"),
1097 MockRead("Content-Length: 5\r\n"),
1098 MockRead("Content-Length: 5\r\n"),
1099 MockRead("Content-Length: 5\r\n\r\n"),
1100 MockRead("Hello"),
1101 };
Ryan Sleevib8d7ea02018-05-07 20:01:011102 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011103 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041104 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1105 EXPECT_EQ("Hello", out.response_data);
1106 }
1107 // 2 dupes and one mismatched.
1108 {
1109 MockRead data_reads[] = {
1110 MockRead("HTTP/1.1 200 OK\r\n"),
1111 MockRead("Content-Length: 10\r\n"),
1112 MockRead("Content-Length: 10\r\n"),
1113 MockRead("Content-Length: 5\r\n\r\n"),
1114 };
Ryan Sleevib8d7ea02018-05-07 20:01:011115 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011116 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041117 }
1118}
1119
bncd16676a2016-07-20 16:23:011120TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001121 MultipleContentLengthHeadersTransferEncoding) {
1122 MockRead data_reads[] = {
1123 MockRead("HTTP/1.1 200 OK\r\n"),
1124 MockRead("Content-Length: 666\r\n"),
1125 MockRead("Content-Length: 1337\r\n"),
1126 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1127 MockRead("5\r\nHello\r\n"),
1128 MockRead("1\r\n"),
1129 MockRead(" \r\n"),
1130 MockRead("5\r\nworld\r\n"),
1131 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061132 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001133 };
Ryan Sleevib8d7ea02018-05-07 20:01:011134 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011135 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001136 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1137 EXPECT_EQ("Hello world", out.response_data);
1138}
1139
[email protected]1628fe92011-10-04 23:04:551140// Next tests deal with http://crbug.com/98895.
1141
1142// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011143TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551144 MockRead data_reads[] = {
1145 MockRead("HTTP/1.1 200 OK\r\n"),
1146 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1147 MockRead("Content-Length: 5\r\n\r\n"),
1148 MockRead("Hello"),
1149 };
Ryan Sleevib8d7ea02018-05-07 20:01:011150 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011151 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551152 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1153 EXPECT_EQ("Hello", out.response_data);
1154}
1155
[email protected]54a9c6e52012-03-21 20:10:591156// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011157TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551158 MockRead data_reads[] = {
1159 MockRead("HTTP/1.1 200 OK\r\n"),
1160 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1161 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1162 MockRead("Content-Length: 5\r\n\r\n"),
1163 MockRead("Hello"),
1164 };
Ryan Sleevib8d7ea02018-05-07 20:01:011165 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011166 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591167 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1168 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551169}
1170
1171// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011172TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551173 MockRead data_reads[] = {
1174 MockRead("HTTP/1.1 200 OK\r\n"),
1175 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1176 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1177 MockRead("Content-Length: 5\r\n\r\n"),
1178 MockRead("Hello"),
1179 };
Ryan Sleevib8d7ea02018-05-07 20:01:011180 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011181 EXPECT_THAT(out.rv,
1182 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551183}
1184
[email protected]54a9c6e52012-03-21 20:10:591185// Checks that two identical Location headers result in no error.
1186// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011187TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551188 MockRead data_reads[] = {
1189 MockRead("HTTP/1.1 302 Redirect\r\n"),
1190 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591191 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551192 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061193 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551194 };
1195
1196 HttpRequestInfo request;
1197 request.method = "GET";
1198 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101199 request.traffic_annotation =
1200 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551201
danakj1fd259a02016-04-16 03:17:091202 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161203 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551204
Ryan Sleevib8d7ea02018-05-07 20:01:011205 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071206 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551207
[email protected]49639fa2011-12-20 23:22:411208 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551209
tfarina42834112016-09-22 13:38:201210 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011211 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551212
robpercival214763f2016-07-01 23:27:011213 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551214
bnc691fda62016-08-12 00:43:161215 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521216 ASSERT_TRUE(response);
1217 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551218 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1219 std::string url;
1220 EXPECT_TRUE(response->headers->IsRedirect(&url));
1221 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471222 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551223}
1224
[email protected]1628fe92011-10-04 23:04:551225// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011226TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551227 MockRead data_reads[] = {
1228 MockRead("HTTP/1.1 302 Redirect\r\n"),
1229 MockRead("Location: http://good.com/\r\n"),
1230 MockRead("Location: http://evil.com/\r\n"),
1231 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061232 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551233 };
Ryan Sleevib8d7ea02018-05-07 20:01:011234 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011235 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551236}
1237
[email protected]ef0faf2e72009-03-05 23:27:231238// Do a request using the HEAD method. Verify that we don't try to read the
1239// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011240TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421241 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231242 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231243 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101244 request.traffic_annotation =
1245 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231246
danakj1fd259a02016-04-16 03:17:091247 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161248 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091249 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161250 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091251 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1252 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271253
[email protected]ef0faf2e72009-03-05 23:27:231254 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131255 MockWrite("HEAD / HTTP/1.1\r\n"
1256 "Host: www.example.org\r\n"
1257 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231258 };
1259 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231260 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1261 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231262
mmenked39192ee2015-12-09 00:57:231263 // No response body because the test stops reading here.
1264 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231265 };
1266
Ryan Sleevib8d7ea02018-05-07 20:01:011267 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071268 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231269
[email protected]49639fa2011-12-20 23:22:411270 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231271
tfarina42834112016-09-22 13:38:201272 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011273 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231274
1275 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011276 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231277
bnc691fda62016-08-12 00:43:161278 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521279 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231280
1281 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521282 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231283 EXPECT_EQ(1234, response->headers->GetContentLength());
1284 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471285 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091286 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1287 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231288
1289 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101290 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231291 bool has_server_header = response->headers->EnumerateHeader(
1292 &iter, "Server", &server_header);
1293 EXPECT_TRUE(has_server_header);
1294 EXPECT_EQ("Blah", server_header);
1295
1296 // Reading should give EOF right away, since there is no message body
1297 // (despite non-zero content-length).
1298 std::string response_data;
bnc691fda62016-08-12 00:43:161299 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011300 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231301 EXPECT_EQ("", response_data);
1302}
1303
bncd16676a2016-07-20 16:23:011304TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091305 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521306
1307 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351308 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1309 MockRead("hello"),
1310 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1311 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061312 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521313 };
Ryan Sleevib8d7ea02018-05-07 20:01:011314 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071315 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521316
[email protected]0b0bf032010-09-21 18:08:501317 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521318 "hello", "world"
1319 };
1320
1321 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421322 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521323 request.method = "GET";
bncce36dca22015-04-21 22:11:231324 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:101325 request.traffic_annotation =
1326 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521327
bnc691fda62016-08-12 00:43:161328 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271329
[email protected]49639fa2011-12-20 23:22:411330 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521331
tfarina42834112016-09-22 13:38:201332 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011333 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521334
1335 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011336 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521337
bnc691fda62016-08-12 00:43:161338 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521339 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521340
wezca1070932016-05-26 20:30:521341 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251342 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471343 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521344
1345 std::string response_data;
bnc691fda62016-08-12 00:43:161346 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011347 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251348 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521349 }
1350}
1351
bncd16676a2016-07-20 16:23:011352TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091353 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221354 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191355 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221356 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271357
[email protected]1c773ea12009-04-28 19:58:421358 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521359 request.method = "POST";
1360 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271361 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:101362 request.traffic_annotation =
1363 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521364
shivanishab9a143952016-09-19 17:23:411365 // Check the upload progress returned before initialization is correct.
1366 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1367 EXPECT_EQ(0u, progress.size());
1368 EXPECT_EQ(0u, progress.position());
1369
danakj1fd259a02016-04-16 03:17:091370 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161371 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271372
initial.commit586acc5fe2008-07-26 22:42:521373 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351374 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1375 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1376 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061377 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521378 };
Ryan Sleevib8d7ea02018-05-07 20:01:011379 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071380 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521381
[email protected]49639fa2011-12-20 23:22:411382 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521383
tfarina42834112016-09-22 13:38:201384 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011385 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521386
1387 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011388 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521389
bnc691fda62016-08-12 00:43:161390 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521391 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521392
wezca1070932016-05-26 20:30:521393 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251394 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521395
1396 std::string response_data;
bnc691fda62016-08-12 00:43:161397 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011398 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251399 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521400}
1401
[email protected]3a2d3662009-03-27 03:49:141402// This test is almost the same as Ignores100 above, but the response contains
1403// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571404// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011405TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421406 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141407 request.method = "GET";
1408 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101409 request.traffic_annotation =
1410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141411
danakj1fd259a02016-04-16 03:17:091412 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161413 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271414
[email protected]3a2d3662009-03-27 03:49:141415 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571416 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1417 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141418 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061419 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141420 };
Ryan Sleevib8d7ea02018-05-07 20:01:011421 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071422 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141423
[email protected]49639fa2011-12-20 23:22:411424 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141425
tfarina42834112016-09-22 13:38:201426 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011427 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141428
1429 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011430 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141431
bnc691fda62016-08-12 00:43:161432 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521433 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141434
wezca1070932016-05-26 20:30:521435 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141436 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1437
1438 std::string response_data;
bnc691fda62016-08-12 00:43:161439 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011440 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141441 EXPECT_EQ("hello world", response_data);
1442}
1443
Andrew Comminos517a92c2019-01-14 17:49:561444TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1445 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381446 base::TimeDelta::FromMilliseconds(10);
1447
1448 HttpRequestInfo request;
1449 request.method = "GET";
1450 request.url = GURL("http://www.foo.com/");
1451 request.traffic_annotation =
1452 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1453
1454 std::vector<MockWrite> data_writes = {
1455 MockWrite(ASYNC, 0,
1456 "GET / HTTP/1.1\r\n"
1457 "Host: www.foo.com\r\n"
1458 "Connection: keep-alive\r\n\r\n"),
1459 };
1460
1461 std::vector<MockRead> data_reads = {
1462 // Write one byte of the status line, followed by a pause.
1463 MockRead(ASYNC, 1, "H"),
1464 MockRead(ASYNC, ERR_IO_PENDING, 2),
1465 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1466 MockRead(ASYNC, 4, "hello world"),
1467 MockRead(SYNCHRONOUS, OK, 5),
1468 };
1469
1470 SequencedSocketData data(data_reads, data_writes);
1471 session_deps_.socket_factory->AddSocketDataProvider(&data);
1472
1473 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1474
1475 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1476
1477 TestCompletionCallback callback;
1478
1479 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1480 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1481
1482 data.RunUntilPaused();
1483 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561484 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381485 data.Resume();
1486
1487 rv = callback.WaitForResult();
1488 EXPECT_THAT(rv, IsOk());
1489
1490 const HttpResponseInfo* response = trans.GetResponseInfo();
1491 ASSERT_TRUE(response);
1492
1493 EXPECT_TRUE(response->headers);
1494 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1495
1496 LoadTimingInfo load_timing_info;
1497 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1498 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1499 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561500 // Ensure we didn't include the delay in the TTFB time.
1501 EXPECT_EQ(load_timing_info.receive_headers_start,
1502 load_timing_info.connect_timing.connect_end);
1503 // Ensure that the mock clock advanced at all.
1504 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1505 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381506
1507 std::string response_data;
1508 rv = ReadTransaction(&trans, &response_data);
1509 EXPECT_THAT(rv, IsOk());
1510 EXPECT_EQ("hello world", response_data);
1511}
1512
1513// Tests that the time-to-first-byte reported in a transaction's load timing
1514// info uses the first response, even if 1XX/informational.
1515void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561516 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381517 base::TimeDelta::FromMilliseconds(10);
1518
1519 HttpRequestInfo request;
1520 request.method = "GET";
1521 request.url = GURL("https://www.foo.com/");
1522 request.traffic_annotation =
1523 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1524
1525 SSLSocketDataProvider ssl(ASYNC, OK);
1526 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1527
1528 std::vector<MockWrite> data_writes;
1529 std::vector<MockRead> data_reads;
1530
1531 spdy::SpdySerializedFrame spdy_req(
1532 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1533
1534 spdy::SpdyHeaderBlock spdy_resp1_headers;
1535 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1536 spdy::SpdySerializedFrame spdy_resp1(
1537 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1538 spdy::SpdySerializedFrame spdy_resp2(
1539 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1540 spdy::SpdySerializedFrame spdy_data(
1541 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1542
1543 if (use_spdy) {
1544 ssl.next_proto = kProtoHTTP2;
1545
1546 data_writes = {CreateMockWrite(spdy_req, 0)};
1547
1548 data_reads = {
1549 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1550 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1551 MockRead(SYNCHRONOUS, OK, 5),
1552 };
1553 } else {
1554 data_writes = {
1555 MockWrite(ASYNC, 0,
1556 "GET / HTTP/1.1\r\n"
1557 "Host: www.foo.com\r\n"
1558 "Connection: keep-alive\r\n\r\n"),
1559 };
1560
1561 data_reads = {
1562 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1563 MockRead(ASYNC, ERR_IO_PENDING, 2),
1564
1565 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1566 MockRead(ASYNC, 4, "hello world"),
1567 MockRead(SYNCHRONOUS, OK, 5),
1568 };
1569 }
1570
1571 SequencedSocketData data(data_reads, data_writes);
1572 session_deps_.socket_factory->AddSocketDataProvider(&data);
1573
1574 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1575
1576 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1577
1578 TestCompletionCallback callback;
1579
1580 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1581 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1582
1583 data.RunUntilPaused();
1584 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1585 // the delay before parsing the 200 response.
1586 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561587 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381588 data.Resume();
1589
1590 rv = callback.WaitForResult();
1591 EXPECT_THAT(rv, IsOk());
1592
1593 const HttpResponseInfo* response = trans.GetResponseInfo();
1594 ASSERT_TRUE(response);
1595
1596 LoadTimingInfo load_timing_info;
1597 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1598 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1599 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561600 // Ensure we didn't include the delay in the TTFB time.
1601 EXPECT_EQ(load_timing_info.receive_headers_start,
1602 load_timing_info.connect_timing.connect_end);
1603 // Ensure that the mock clock advanced at all.
1604 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1605 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381606
1607 std::string response_data;
1608 rv = ReadTransaction(&trans, &response_data);
1609 EXPECT_THAT(rv, IsOk());
1610 EXPECT_EQ("hello world", response_data);
1611}
1612
Andrew Comminos517a92c2019-01-14 17:49:561613TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381614 Check100ResponseTiming(false /* use_spdy */);
1615}
1616
Andrew Comminos517a92c2019-01-14 17:49:561617TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381618 Check100ResponseTiming(true /* use_spdy */);
1619}
1620
bncd16676a2016-07-20 16:23:011621TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081622 HttpRequestInfo request;
1623 request.method = "POST";
1624 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101625 request.traffic_annotation =
1626 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081627
danakj1fd259a02016-04-16 03:17:091628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161629 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081630
1631 MockRead data_reads[] = {
1632 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1633 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381634 };
Ryan Sleevib8d7ea02018-05-07 20:01:011635 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081636 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381637
zmo9528c9f42015-08-04 22:12:081638 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381639
tfarina42834112016-09-22 13:38:201640 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011641 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381642
zmo9528c9f42015-08-04 22:12:081643 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011644 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381645
zmo9528c9f42015-08-04 22:12:081646 std::string response_data;
bnc691fda62016-08-12 00:43:161647 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011648 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081649 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381650}
1651
bncd16676a2016-07-20 16:23:011652TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381653 HttpRequestInfo request;
1654 request.method = "POST";
1655 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101656 request.traffic_annotation =
1657 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381658
danakj1fd259a02016-04-16 03:17:091659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161660 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271661
[email protected]ee9410e72010-01-07 01:42:381662 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061663 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381664 };
Ryan Sleevib8d7ea02018-05-07 20:01:011665 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071666 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381667
[email protected]49639fa2011-12-20 23:22:411668 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381669
tfarina42834112016-09-22 13:38:201670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381672
1673 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011674 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381675}
1676
[email protected]23e482282013-06-14 16:08:021677void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511678 const MockWrite* write_failure,
1679 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421680 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521681 request.method = "GET";
1682 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101683 request.traffic_annotation =
1684 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521685
vishal.b62985ca92015-04-17 08:45:511686 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071687 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091688 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271689
[email protected]202965992011-12-07 23:04:511690 // Written data for successfully sending both requests.
1691 MockWrite data1_writes[] = {
1692 MockWrite("GET / HTTP/1.1\r\n"
1693 "Host: www.foo.com\r\n"
1694 "Connection: keep-alive\r\n\r\n"),
1695 MockWrite("GET / HTTP/1.1\r\n"
1696 "Host: www.foo.com\r\n"
1697 "Connection: keep-alive\r\n\r\n")
1698 };
1699
1700 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521701 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351702 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1703 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061704 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521705 };
[email protected]202965992011-12-07 23:04:511706
1707 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491708 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511709 data1_writes[1] = *write_failure;
1710 } else {
1711 ASSERT_TRUE(read_failure);
1712 data1_reads[2] = *read_failure;
1713 }
1714
Ryan Sleevib8d7ea02018-05-07 20:01:011715 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071716 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521717
1718 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351719 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1720 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061721 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521722 };
Ryan Sleevib8d7ea02018-05-07 20:01:011723 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071724 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521725
thestig9d3bb0c2015-01-24 00:49:511726 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521727 "hello", "world"
1728 };
1729
mikecironef22f9812016-10-04 03:40:191730 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521731 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411732 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521733
bnc691fda62016-08-12 00:43:161734 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521735
tfarina42834112016-09-22 13:38:201736 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011737 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521738
1739 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011740 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521741
[email protected]58e32bb2013-01-21 18:23:251742 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161743 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251744 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1745 if (i == 0) {
1746 first_socket_log_id = load_timing_info.socket_log_id;
1747 } else {
1748 // The second request should be using a new socket.
1749 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1750 }
1751
bnc691fda62016-08-12 00:43:161752 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521753 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521754
wezca1070932016-05-26 20:30:521755 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471756 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251757 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521758
1759 std::string response_data;
bnc691fda62016-08-12 00:43:161760 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011761 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251762 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521763 }
1764}
[email protected]3d2a59b2008-09-26 19:44:251765
[email protected]a34f61ee2014-03-18 20:59:491766void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1767 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101768 const MockRead* read_failure,
1769 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491770 HttpRequestInfo request;
1771 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101772 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101773 request.traffic_annotation =
1774 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491775
vishal.b62985ca92015-04-17 08:45:511776 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491777 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091778 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491779
[email protected]09356c652014-03-25 15:36:101780 SSLSocketDataProvider ssl1(ASYNC, OK);
1781 SSLSocketDataProvider ssl2(ASYNC, OK);
1782 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361783 ssl1.next_proto = kProtoHTTP2;
1784 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101785 }
1786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1787 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491788
[email protected]09356c652014-03-25 15:36:101789 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131790 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491791 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131792 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351793 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131794 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191795 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491796
[email protected]09356c652014-03-25 15:36:101797 // HTTP/1.1 versions of the request and response.
1798 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1799 "Host: www.foo.com\r\n"
1800 "Connection: keep-alive\r\n\r\n";
1801 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1802 const char kHttpData[] = "hello";
1803
1804 std::vector<MockRead> data1_reads;
1805 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491806 if (write_failure) {
1807 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101808 data1_writes.push_back(*write_failure);
1809 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491810 } else {
1811 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101812 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411813 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101814 } else {
1815 data1_writes.push_back(MockWrite(kHttpRequest));
1816 }
1817 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491818 }
1819
Ryan Sleevib8d7ea02018-05-07 20:01:011820 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491821 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1822
[email protected]09356c652014-03-25 15:36:101823 std::vector<MockRead> data2_reads;
1824 std::vector<MockWrite> data2_writes;
1825
1826 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411827 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101828
bncdf80d44fd2016-07-15 20:27:411829 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1830 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101831 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1832 } else {
1833 data2_writes.push_back(
1834 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1835
1836 data2_reads.push_back(
1837 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1838 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1839 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1840 }
Ryan Sleevib8d7ea02018-05-07 20:01:011841 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491842 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1843
1844 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591845 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491846 // Wait for the preconnect to complete.
1847 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1848 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231849 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491850
1851 // Make the request.
1852 TestCompletionCallback callback;
1853
bnc691fda62016-08-12 00:43:161854 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491855
tfarina42834112016-09-22 13:38:201856 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011857 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491858
1859 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011860 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491861
1862 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161863 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101864 TestLoadTimingNotReused(
1865 load_timing_info,
1866 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491867
bnc691fda62016-08-12 00:43:161868 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521869 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491870
wezca1070932016-05-26 20:30:521871 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021872 if (response->was_fetched_via_spdy) {
1873 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1874 } else {
1875 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1876 }
[email protected]a34f61ee2014-03-18 20:59:491877
1878 std::string response_data;
bnc691fda62016-08-12 00:43:161879 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011880 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101881 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491882}
1883
Biljith Jayan45a41722017-08-16 18:43:141884// Test that we do not retry indefinitely when a server sends an error like
1885// ERR_SPDY_PING_FAILED, ERR_SPDY_SERVER_REFUSED_STREAM,
1886// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1887TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1888 HttpRequestInfo request;
1889 request.method = "GET";
1890 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101891 request.traffic_annotation =
1892 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141893
1894 // Check whether we give up after the third try.
1895
1896 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131897 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141898 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131899 spdy::SpdySerializedFrame spdy_response_go_away(
1900 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011901 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1902 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141903
1904 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011905 StaticSocketDataProvider data1(data_read1, data_write);
1906 StaticSocketDataProvider data2(data_read1, data_write);
1907 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141908
1909 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1910 AddSSLSocketData();
1911 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1912 AddSSLSocketData();
1913 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1914 AddSSLSocketData();
1915
1916 TestCompletionCallback callback;
1917 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1918 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1919
1920 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1921 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1922
1923 rv = callback.WaitForResult();
1924 EXPECT_THAT(rv, IsError(ERR_SPDY_SERVER_REFUSED_STREAM));
1925}
1926
1927TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1928 HttpRequestInfo request;
1929 request.method = "GET";
1930 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:101931 request.traffic_annotation =
1932 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141933
1934 // Check whether we try atleast thrice before giving up.
1935
1936 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131937 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141938 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131939 spdy::SpdySerializedFrame spdy_response_go_away(
1940 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011941 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1942 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141943
1944 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131945 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141946 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131947 spdy::SpdySerializedFrame spdy_data(
1948 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141949 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1950 CreateMockRead(spdy_data, 2)};
1951
1952 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011953 StaticSocketDataProvider data1(data_read1, data_write);
1954 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141955 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011956 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141957
1958 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1959 AddSSLSocketData();
1960 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1961 AddSSLSocketData();
1962 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1963 AddSSLSocketData();
1964
1965 TestCompletionCallback callback;
1966 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1967 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1968
1969 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1970 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1971
1972 rv = callback.WaitForResult();
1973 EXPECT_THAT(rv, IsOk());
1974}
1975
bncd16676a2016-07-20 16:23:011976TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061977 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351978 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511979}
1980
bncd16676a2016-07-20 16:23:011981TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061982 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351983 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251984}
1985
bncd16676a2016-07-20 16:23:011986TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061987 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351988 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251989}
1990
[email protected]d58ceea82014-06-04 10:55:541991// Make sure that on a 408 response (Request Timeout), the request is retried,
1992// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011993TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541994 MockRead read_failure(SYNCHRONOUS,
1995 "HTTP/1.1 408 Request Timeout\r\n"
1996 "Connection: Keep-Alive\r\n"
1997 "Content-Length: 6\r\n\r\n"
1998 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351999 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:542000}
2001
bncd16676a2016-07-20 16:23:012002TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:492003 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352004 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:492005}
2006
bncd16676a2016-07-20 16:23:012007TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:492008 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352009 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:492010}
2011
bncd16676a2016-07-20 16:23:012012TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:492013 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352014 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:102015}
2016
bncd16676a2016-07-20 16:23:012017TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102018 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352019 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:102020}
2021
[email protected]d58ceea82014-06-04 10:55:542022// Make sure that on a 408 response (Request Timeout), the request is retried,
2023// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:012024TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:542025 MockRead read_failure(SYNCHRONOUS,
2026 "HTTP/1.1 408 Request Timeout\r\n"
2027 "Connection: Keep-Alive\r\n"
2028 "Content-Length: 6\r\n\r\n"
2029 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352030 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2031 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:542032}
2033
bncd16676a2016-07-20 16:23:012034TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:102035 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352036 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:102037}
2038
bncd16676a2016-07-20 16:23:012039TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:102040 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352041 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102042}
2043
bncd16676a2016-07-20 16:23:012044TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:102045 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352046 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102047}
2048
bncd16676a2016-07-20 16:23:012049TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102050 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352051 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:492052}
2053
bncd16676a2016-07-20 16:23:012054TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422055 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252056 request.method = "GET";
bncce36dca22015-04-21 22:11:232057 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102058 request.traffic_annotation =
2059 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252060
danakj1fd259a02016-04-16 03:17:092061 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162062 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272063
[email protected]3d2a59b2008-09-26 19:44:252064 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062065 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352066 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2067 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062068 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252069 };
Ryan Sleevib8d7ea02018-05-07 20:01:012070 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072071 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252072
[email protected]49639fa2011-12-20 23:22:412073 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252074
tfarina42834112016-09-22 13:38:202075 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012076 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252077
2078 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012079 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592080
2081 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162082 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592083 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252084}
2085
2086// What do various browsers do when the server closes a non-keepalive
2087// connection without sending any response header or body?
2088//
2089// IE7: error page
2090// Safari 3.1.2 (Windows): error page
2091// Firefox 3.0.1: blank page
2092// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422093// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2094// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012095TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252096 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062097 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352098 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2099 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062100 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252101 };
Ryan Sleevib8d7ea02018-05-07 20:01:012102 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012103 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252104}
[email protected]1826a402014-01-08 15:40:482105
[email protected]7a5378b2012-11-04 03:25:172106// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2107// tests. There was a bug causing HttpNetworkTransaction to hang in the
2108// destructor in such situations.
2109// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012110TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172111 HttpRequestInfo request;
2112 request.method = "GET";
bncce36dca22015-04-21 22:11:232113 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102114 request.traffic_annotation =
2115 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172116
danakj1fd259a02016-04-16 03:17:092117 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582118 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192119 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172120
2121 MockRead data_reads[] = {
2122 MockRead("HTTP/1.0 200 OK\r\n"),
2123 MockRead("Connection: keep-alive\r\n"),
2124 MockRead("Content-Length: 100\r\n\r\n"),
2125 MockRead("hello"),
2126 MockRead(SYNCHRONOUS, 0),
2127 };
Ryan Sleevib8d7ea02018-05-07 20:01:012128 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072129 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172130
2131 TestCompletionCallback callback;
2132
tfarina42834112016-09-22 13:38:202133 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012134 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172135
2136 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012137 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172138
Victor Costan9c7302b2018-08-27 16:39:442139 scoped_refptr<IOBufferWithSize> io_buf =
2140 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502141 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172142 if (rv == ERR_IO_PENDING)
2143 rv = callback.WaitForResult();
2144 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502145 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012146 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172147
2148 trans.reset();
fdoray92e35a72016-06-10 15:54:552149 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172150 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2151}
2152
bncd16676a2016-07-20 16:23:012153TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172154 HttpRequestInfo request;
2155 request.method = "GET";
bncce36dca22015-04-21 22:11:232156 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102157 request.traffic_annotation =
2158 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172159
danakj1fd259a02016-04-16 03:17:092160 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582161 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192162 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172163
2164 MockRead data_reads[] = {
2165 MockRead("HTTP/1.0 200 OK\r\n"),
2166 MockRead("Connection: keep-alive\r\n"),
2167 MockRead("Content-Length: 100\r\n\r\n"),
2168 MockRead(SYNCHRONOUS, 0),
2169 };
Ryan Sleevib8d7ea02018-05-07 20:01:012170 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072171 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172172
2173 TestCompletionCallback callback;
2174
tfarina42834112016-09-22 13:38:202175 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012176 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172177
2178 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012179 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172180
Victor Costan9c7302b2018-08-27 16:39:442181 scoped_refptr<IOBufferWithSize> io_buf(
2182 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502183 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172184 if (rv == ERR_IO_PENDING)
2185 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012186 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172187
2188 trans.reset();
fdoray92e35a72016-06-10 15:54:552189 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172190 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2191}
2192
[email protected]0b0bf032010-09-21 18:08:502193// Test that we correctly reuse a keep-alive connection after not explicitly
2194// reading the body.
bncd16676a2016-07-20 16:23:012195TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132196 HttpRequestInfo request;
2197 request.method = "GET";
2198 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102199 request.traffic_annotation =
2200 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132201
vishal.b62985ca92015-04-17 08:45:512202 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072203 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092204 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272205
mmenkecc2298e2015-12-07 18:20:182206 const char* request_data =
2207 "GET / HTTP/1.1\r\n"
2208 "Host: www.foo.com\r\n"
2209 "Connection: keep-alive\r\n\r\n";
2210 MockWrite data_writes[] = {
2211 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2212 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2213 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2214 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2215 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2216 };
2217
[email protected]0b0bf032010-09-21 18:08:502218 // Note that because all these reads happen in the same
2219 // StaticSocketDataProvider, it shows that the same socket is being reused for
2220 // all transactions.
mmenkecc2298e2015-12-07 18:20:182221 MockRead data_reads[] = {
2222 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2223 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2224 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2225 MockRead(ASYNC, 7,
2226 "HTTP/1.1 302 Found\r\n"
2227 "Content-Length: 0\r\n\r\n"),
2228 MockRead(ASYNC, 9,
2229 "HTTP/1.1 302 Found\r\n"
2230 "Content-Length: 5\r\n\r\n"
2231 "hello"),
2232 MockRead(ASYNC, 11,
2233 "HTTP/1.1 301 Moved Permanently\r\n"
2234 "Content-Length: 0\r\n\r\n"),
2235 MockRead(ASYNC, 13,
2236 "HTTP/1.1 301 Moved Permanently\r\n"
2237 "Content-Length: 5\r\n\r\n"
2238 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132239
mmenkecc2298e2015-12-07 18:20:182240 // In the next two rounds, IsConnectedAndIdle returns false, due to
2241 // the set_busy_before_sync_reads(true) call, while the
2242 // HttpNetworkTransaction is being shut down, but the socket is still
2243 // reuseable. See http://crbug.com/544255.
2244 MockRead(ASYNC, 15,
2245 "HTTP/1.1 200 Hunky-Dory\r\n"
2246 "Content-Length: 5\r\n\r\n"),
2247 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132248
mmenkecc2298e2015-12-07 18:20:182249 MockRead(ASYNC, 18,
2250 "HTTP/1.1 200 Hunky-Dory\r\n"
2251 "Content-Length: 5\r\n\r\n"
2252 "he"),
2253 MockRead(SYNCHRONOUS, 19, "llo"),
2254
2255 // The body of the final request is actually read.
2256 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2257 MockRead(ASYNC, 22, "hello"),
2258 };
Ryan Sleevib8d7ea02018-05-07 20:01:012259 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182260 data.set_busy_before_sync_reads(true);
2261 session_deps_.socket_factory->AddSocketDataProvider(&data);
2262
Avi Drissman4365a4782018-12-28 19:26:242263 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502264 std::string response_lines[kNumUnreadBodies];
2265
mikecironef22f9812016-10-04 03:40:192266 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182267 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412268 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132269
Jeremy Roman0579ed62017-08-29 15:56:192270 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582271 session.get());
[email protected]fc31d6a42010-06-24 18:05:132272
tfarina42834112016-09-22 13:38:202273 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012274 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132275
[email protected]58e32bb2013-01-21 18:23:252276 LoadTimingInfo load_timing_info;
2277 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2278 if (i == 0) {
2279 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2280 first_socket_log_id = load_timing_info.socket_log_id;
2281 } else {
2282 TestLoadTimingReused(load_timing_info);
2283 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2284 }
2285
[email protected]fc31d6a42010-06-24 18:05:132286 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182287 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132288
mmenkecc2298e2015-12-07 18:20:182289 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502290 response_lines[i] = response->headers->GetStatusLine();
2291
mmenkecc2298e2015-12-07 18:20:182292 // Delete the transaction without reading the response bodies. Then spin
2293 // the message loop, so the response bodies are drained.
2294 trans.reset();
2295 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132296 }
[email protected]0b0bf032010-09-21 18:08:502297
2298 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182299 "HTTP/1.1 204 No Content",
2300 "HTTP/1.1 205 Reset Content",
2301 "HTTP/1.1 304 Not Modified",
2302 "HTTP/1.1 302 Found",
2303 "HTTP/1.1 302 Found",
2304 "HTTP/1.1 301 Moved Permanently",
2305 "HTTP/1.1 301 Moved Permanently",
2306 "HTTP/1.1 200 Hunky-Dory",
2307 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502308 };
2309
Avi Drissman4365a4782018-12-28 19:26:242310 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272311 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502312
2313 for (int i = 0; i < kNumUnreadBodies; ++i)
2314 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2315
[email protected]49639fa2011-12-20 23:22:412316 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162317 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202318 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012319 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162320 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182321 ASSERT_TRUE(response);
2322 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502323 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2324 std::string response_data;
bnc691fda62016-08-12 00:43:162325 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012326 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502327 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132328}
2329
mmenke5f94fda2016-06-02 20:54:132330// Sockets that receive extra data after a response is complete should not be
2331// reused.
bncd16676a2016-07-20 16:23:012332TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132333 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2334 MockWrite data_writes1[] = {
2335 MockWrite("HEAD / HTTP/1.1\r\n"
2336 "Host: www.borked.com\r\n"
2337 "Connection: keep-alive\r\n\r\n"),
2338 };
2339
2340 MockRead data_reads1[] = {
2341 MockRead("HTTP/1.1 200 OK\r\n"
2342 "Connection: keep-alive\r\n"
2343 "Content-Length: 22\r\n\r\n"
2344 "This server is borked."),
2345 };
2346
2347 MockWrite data_writes2[] = {
2348 MockWrite("GET /foo HTTP/1.1\r\n"
2349 "Host: www.borked.com\r\n"
2350 "Connection: keep-alive\r\n\r\n"),
2351 };
2352
2353 MockRead data_reads2[] = {
2354 MockRead("HTTP/1.1 200 OK\r\n"
2355 "Content-Length: 3\r\n\r\n"
2356 "foo"),
2357 };
Ryan Sleevib8d7ea02018-05-07 20:01:012358 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132359 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012360 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132361 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2362
2363 TestCompletionCallback callback;
2364 HttpRequestInfo request1;
2365 request1.method = "HEAD";
2366 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102367 request1.traffic_annotation =
2368 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132369
bnc87dcefc2017-05-25 12:47:582370 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192371 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202372 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012373 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132374
2375 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2376 ASSERT_TRUE(response1);
2377 ASSERT_TRUE(response1->headers);
2378 EXPECT_EQ(200, response1->headers->response_code());
2379 EXPECT_TRUE(response1->headers->IsKeepAlive());
2380
2381 std::string response_data1;
robpercival214763f2016-07-01 23:27:012382 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132383 EXPECT_EQ("", response_data1);
2384 // Deleting the transaction attempts to release the socket back into the
2385 // socket pool.
2386 trans1.reset();
2387
2388 HttpRequestInfo request2;
2389 request2.method = "GET";
2390 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102391 request2.traffic_annotation =
2392 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132393
bnc87dcefc2017-05-25 12:47:582394 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192395 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202396 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012397 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132398
2399 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2400 ASSERT_TRUE(response2);
2401 ASSERT_TRUE(response2->headers);
2402 EXPECT_EQ(200, response2->headers->response_code());
2403
2404 std::string response_data2;
robpercival214763f2016-07-01 23:27:012405 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132406 EXPECT_EQ("foo", response_data2);
2407}
2408
bncd16676a2016-07-20 16:23:012409TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132410 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2411 MockWrite data_writes1[] = {
2412 MockWrite("GET / HTTP/1.1\r\n"
2413 "Host: www.borked.com\r\n"
2414 "Connection: keep-alive\r\n\r\n"),
2415 };
2416
2417 MockRead data_reads1[] = {
2418 MockRead("HTTP/1.1 200 OK\r\n"
2419 "Connection: keep-alive\r\n"
2420 "Content-Length: 22\r\n\r\n"
2421 "This server is borked."
2422 "Bonus data!"),
2423 };
2424
2425 MockWrite data_writes2[] = {
2426 MockWrite("GET /foo HTTP/1.1\r\n"
2427 "Host: www.borked.com\r\n"
2428 "Connection: keep-alive\r\n\r\n"),
2429 };
2430
2431 MockRead data_reads2[] = {
2432 MockRead("HTTP/1.1 200 OK\r\n"
2433 "Content-Length: 3\r\n\r\n"
2434 "foo"),
2435 };
Ryan Sleevib8d7ea02018-05-07 20:01:012436 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132437 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012438 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132439 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2440
2441 TestCompletionCallback callback;
2442 HttpRequestInfo request1;
2443 request1.method = "GET";
2444 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102445 request1.traffic_annotation =
2446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132447
bnc87dcefc2017-05-25 12:47:582448 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192449 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202450 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012451 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132452
2453 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2454 ASSERT_TRUE(response1);
2455 ASSERT_TRUE(response1->headers);
2456 EXPECT_EQ(200, response1->headers->response_code());
2457 EXPECT_TRUE(response1->headers->IsKeepAlive());
2458
2459 std::string response_data1;
robpercival214763f2016-07-01 23:27:012460 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132461 EXPECT_EQ("This server is borked.", response_data1);
2462 // Deleting the transaction attempts to release the socket back into the
2463 // socket pool.
2464 trans1.reset();
2465
2466 HttpRequestInfo request2;
2467 request2.method = "GET";
2468 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102469 request2.traffic_annotation =
2470 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132471
bnc87dcefc2017-05-25 12:47:582472 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192473 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202474 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012475 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132476
2477 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2478 ASSERT_TRUE(response2);
2479 ASSERT_TRUE(response2->headers);
2480 EXPECT_EQ(200, response2->headers->response_code());
2481
2482 std::string response_data2;
robpercival214763f2016-07-01 23:27:012483 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132484 EXPECT_EQ("foo", response_data2);
2485}
2486
bncd16676a2016-07-20 16:23:012487TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132488 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2489 MockWrite data_writes1[] = {
2490 MockWrite("GET / HTTP/1.1\r\n"
2491 "Host: www.borked.com\r\n"
2492 "Connection: keep-alive\r\n\r\n"),
2493 };
2494
2495 MockRead data_reads1[] = {
2496 MockRead("HTTP/1.1 200 OK\r\n"
2497 "Connection: keep-alive\r\n"
2498 "Transfer-Encoding: chunked\r\n\r\n"),
2499 MockRead("16\r\nThis server is borked.\r\n"),
2500 MockRead("0\r\n\r\nBonus data!"),
2501 };
2502
2503 MockWrite data_writes2[] = {
2504 MockWrite("GET /foo HTTP/1.1\r\n"
2505 "Host: www.borked.com\r\n"
2506 "Connection: keep-alive\r\n\r\n"),
2507 };
2508
2509 MockRead data_reads2[] = {
2510 MockRead("HTTP/1.1 200 OK\r\n"
2511 "Content-Length: 3\r\n\r\n"
2512 "foo"),
2513 };
Ryan Sleevib8d7ea02018-05-07 20:01:012514 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132515 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012516 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132517 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2518
2519 TestCompletionCallback callback;
2520 HttpRequestInfo request1;
2521 request1.method = "GET";
2522 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102523 request1.traffic_annotation =
2524 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132525
bnc87dcefc2017-05-25 12:47:582526 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192527 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202528 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012529 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132530
2531 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2532 ASSERT_TRUE(response1);
2533 ASSERT_TRUE(response1->headers);
2534 EXPECT_EQ(200, response1->headers->response_code());
2535 EXPECT_TRUE(response1->headers->IsKeepAlive());
2536
2537 std::string response_data1;
robpercival214763f2016-07-01 23:27:012538 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132539 EXPECT_EQ("This server is borked.", response_data1);
2540 // Deleting the transaction attempts to release the socket back into the
2541 // socket pool.
2542 trans1.reset();
2543
2544 HttpRequestInfo request2;
2545 request2.method = "GET";
2546 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e2018-02-07 07:41:102547 request2.traffic_annotation =
2548 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132549
bnc87dcefc2017-05-25 12:47:582550 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192551 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202552 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012553 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132554
2555 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2556 ASSERT_TRUE(response2);
2557 ASSERT_TRUE(response2->headers);
2558 EXPECT_EQ(200, response2->headers->response_code());
2559
2560 std::string response_data2;
robpercival214763f2016-07-01 23:27:012561 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132562 EXPECT_EQ("foo", response_data2);
2563}
2564
2565// This is a little different from the others - it tests the case that the
2566// HttpStreamParser doesn't know if there's extra data on a socket or not when
2567// the HttpNetworkTransaction is torn down, because the response body hasn't
2568// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012569TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132570 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2571 MockWrite data_writes1[] = {
2572 MockWrite("GET / HTTP/1.1\r\n"
2573 "Host: www.borked.com\r\n"
2574 "Connection: keep-alive\r\n\r\n"),
2575 };
2576
2577 MockRead data_reads1[] = {
2578 MockRead("HTTP/1.1 200 OK\r\n"
2579 "Connection: keep-alive\r\n"
2580 "Transfer-Encoding: chunked\r\n\r\n"),
2581 MockRead("16\r\nThis server is borked.\r\n"),
2582 MockRead("0\r\n\r\nBonus data!"),
2583 };
Ryan Sleevib8d7ea02018-05-07 20:01:012584 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132585 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2586
2587 TestCompletionCallback callback;
2588 HttpRequestInfo request1;
2589 request1.method = "GET";
2590 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e2018-02-07 07:41:102591 request1.traffic_annotation =
2592 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132593
bnc87dcefc2017-05-25 12:47:582594 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192595 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582596 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012597 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132598
bnc87dcefc2017-05-25 12:47:582599 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132600 ASSERT_TRUE(response1);
2601 ASSERT_TRUE(response1->headers);
2602 EXPECT_EQ(200, response1->headers->response_code());
2603 EXPECT_TRUE(response1->headers->IsKeepAlive());
2604
2605 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2606 // response body.
bnc87dcefc2017-05-25 12:47:582607 trans.reset();
mmenke5f94fda2016-06-02 20:54:132608
2609 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2610 // socket can't be reused, rather than returning it to the socket pool.
2611 base::RunLoop().RunUntilIdle();
2612
2613 // There should be no idle sockets in the pool.
2614 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2615}
2616
[email protected]038e9a32008-10-08 22:40:162617// Test the request-challenge-retry sequence for basic auth.
2618// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012619TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422620 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162621 request.method = "GET";
bncce36dca22015-04-21 22:11:232622 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102623 request.traffic_annotation =
2624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162625
vishal.b62985ca92015-04-17 08:45:512626 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072627 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162629 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272630
[email protected]f9ee6b52008-11-08 06:46:232631 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232632 MockWrite(
2633 "GET / HTTP/1.1\r\n"
2634 "Host: www.example.org\r\n"
2635 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232636 };
2637
[email protected]038e9a32008-10-08 22:40:162638 MockRead data_reads1[] = {
2639 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2640 // Give a couple authenticate options (only the middle one is actually
2641 // supported).
[email protected]22927ad2009-09-21 19:56:192642 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162643 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2644 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2645 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2646 // Large content-length -- won't matter, as connection will be reset.
2647 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062648 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162649 };
2650
2651 // After calling trans->RestartWithAuth(), this is the request we should
2652 // be issuing -- the final header line contains the credentials.
2653 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232654 MockWrite(
2655 "GET / HTTP/1.1\r\n"
2656 "Host: www.example.org\r\n"
2657 "Connection: keep-alive\r\n"
2658 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162659 };
2660
2661 // Lastly, the server responds with the actual content.
2662 MockRead data_reads2[] = {
2663 MockRead("HTTP/1.0 200 OK\r\n"),
2664 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2665 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062666 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162667 };
2668
Ryan Sleevib8d7ea02018-05-07 20:01:012669 StaticSocketDataProvider data1(data_reads1, data_writes1);
2670 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072671 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2672 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162673
[email protected]49639fa2011-12-20 23:22:412674 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162675
tfarina42834112016-09-22 13:38:202676 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162678
2679 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012680 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162681
[email protected]58e32bb2013-01-21 18:23:252682 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162683 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252684 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2685
Ryan Sleevib8d7ea02018-05-07 20:01:012686 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162687 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012688 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162689 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192690
bnc691fda62016-08-12 00:43:162691 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522692 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582693 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162694
[email protected]49639fa2011-12-20 23:22:412695 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162696
bnc691fda62016-08-12 00:43:162697 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012698 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162699
2700 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012701 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162702
[email protected]58e32bb2013-01-21 18:23:252703 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162704 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252705 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2706 // The load timing after restart should have a new socket ID, and times after
2707 // those of the first load timing.
2708 EXPECT_LE(load_timing_info1.receive_headers_end,
2709 load_timing_info2.connect_timing.connect_start);
2710 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2711
Ryan Sleevib8d7ea02018-05-07 20:01:012712 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162713 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012714 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162715 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192716
bnc691fda62016-08-12 00:43:162717 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522718 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582719 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162720 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162721}
2722
ttuttled9dbc652015-09-29 20:00:592723// Test the request-challenge-retry sequence for basic auth.
2724// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012725TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592726 HttpRequestInfo request;
2727 request.method = "GET";
2728 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102729 request.traffic_annotation =
2730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592731
2732 TestNetLog log;
2733 MockHostResolver* resolver = new MockHostResolver();
2734 session_deps_.net_log = &log;
2735 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092736 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162737 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592738
2739 resolver->rules()->ClearRules();
2740 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2741
2742 MockWrite data_writes1[] = {
2743 MockWrite("GET / HTTP/1.1\r\n"
2744 "Host: www.example.org\r\n"
2745 "Connection: keep-alive\r\n\r\n"),
2746 };
2747
2748 MockRead data_reads1[] = {
2749 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2750 // Give a couple authenticate options (only the middle one is actually
2751 // supported).
2752 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2753 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2754 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2755 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2756 // Large content-length -- won't matter, as connection will be reset.
2757 MockRead("Content-Length: 10000\r\n\r\n"),
2758 MockRead(SYNCHRONOUS, ERR_FAILED),
2759 };
2760
2761 // After calling trans->RestartWithAuth(), this is the request we should
2762 // be issuing -- the final header line contains the credentials.
2763 MockWrite data_writes2[] = {
2764 MockWrite("GET / HTTP/1.1\r\n"
2765 "Host: www.example.org\r\n"
2766 "Connection: keep-alive\r\n"
2767 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2768 };
2769
2770 // Lastly, the server responds with the actual content.
2771 MockRead data_reads2[] = {
2772 MockRead("HTTP/1.0 200 OK\r\n"),
2773 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2774 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2775 };
2776
Ryan Sleevib8d7ea02018-05-07 20:01:012777 StaticSocketDataProvider data1(data_reads1, data_writes1);
2778 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592779 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2780 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2781
2782 TestCompletionCallback callback1;
2783
bnc691fda62016-08-12 00:43:162784 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202785 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592786
2787 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162788 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592789 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2790
Ryan Sleevib8d7ea02018-05-07 20:01:012791 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162792 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012793 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162794 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592795
bnc691fda62016-08-12 00:43:162796 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592797 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582798 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592799
2800 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162801 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592802 ASSERT_FALSE(endpoint.address().empty());
2803 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2804
2805 resolver->rules()->ClearRules();
2806 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2807
2808 TestCompletionCallback callback2;
2809
bnc691fda62016-08-12 00:43:162810 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592811 AuthCredentials(kFoo, kBar), callback2.callback())));
2812
2813 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162814 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592815 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2816 // The load timing after restart should have a new socket ID, and times after
2817 // those of the first load timing.
2818 EXPECT_LE(load_timing_info1.receive_headers_end,
2819 load_timing_info2.connect_timing.connect_start);
2820 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2821
Ryan Sleevib8d7ea02018-05-07 20:01:012822 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162823 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012824 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162825 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592826
bnc691fda62016-08-12 00:43:162827 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592828 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582829 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592830 EXPECT_EQ(100, response->headers->GetContentLength());
2831
bnc691fda62016-08-12 00:43:162832 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592833 ASSERT_FALSE(endpoint.address().empty());
2834 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2835}
2836
David Benjamin83ddfb32018-03-30 01:07:522837// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2838// will eventually give up.
2839TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2840 HttpRequestInfo request;
2841 request.method = "GET";
2842 request.url = GURL("http://www.example.org/");
2843 request.traffic_annotation =
2844 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2845
2846 TestNetLog log;
2847 session_deps_.net_log = &log;
2848 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2849 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2850
2851 MockWrite data_writes[] = {
2852 MockWrite("GET / HTTP/1.1\r\n"
2853 "Host: www.example.org\r\n"
2854 "Connection: keep-alive\r\n\r\n"),
2855 };
2856
2857 MockRead data_reads[] = {
2858 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2859 // Give a couple authenticate options (only the middle one is actually
2860 // supported).
2861 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2862 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2863 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2864 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2865 // Large content-length -- won't matter, as connection will be reset.
2866 MockRead("Content-Length: 10000\r\n\r\n"),
2867 MockRead(SYNCHRONOUS, ERR_FAILED),
2868 };
2869
2870 // After calling trans->RestartWithAuth(), this is the request we should
2871 // be issuing -- the final header line contains the credentials.
2872 MockWrite data_writes_restart[] = {
2873 MockWrite("GET / HTTP/1.1\r\n"
2874 "Host: www.example.org\r\n"
2875 "Connection: keep-alive\r\n"
2876 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2877 };
2878
Ryan Sleevib8d7ea02018-05-07 20:01:012879 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522880 session_deps_.socket_factory->AddSocketDataProvider(&data);
2881
2882 TestCompletionCallback callback;
2883 int rv = callback.GetResult(
2884 trans.Start(&request, callback.callback(), NetLogWithSource()));
2885
2886 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2887 for (int i = 0; i < 32; i++) {
2888 // Check the previous response was a 401.
2889 EXPECT_THAT(rv, IsOk());
2890 const HttpResponseInfo* response = trans.GetResponseInfo();
2891 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582892 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522893
2894 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012895 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522896 session_deps_.socket_factory->AddSocketDataProvider(
2897 data_restarts.back().get());
2898 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2899 callback.callback()));
2900 }
2901
2902 // After too many tries, the transaction should have given up.
2903 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2904}
2905
bncd16676a2016-07-20 16:23:012906TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462907 HttpRequestInfo request;
2908 request.method = "GET";
bncce36dca22015-04-21 22:11:232909 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292910 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:102911 request.traffic_annotation =
2912 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462913
danakj1fd259a02016-04-16 03:17:092914 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162915 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272916
[email protected]861fcd52009-08-26 02:33:462917 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232918 MockWrite(
2919 "GET / HTTP/1.1\r\n"
2920 "Host: www.example.org\r\n"
2921 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462922 };
2923
2924 MockRead data_reads[] = {
2925 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2926 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2927 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2928 // Large content-length -- won't matter, as connection will be reset.
2929 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062930 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462931 };
2932
Ryan Sleevib8d7ea02018-05-07 20:01:012933 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072934 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412935 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462936
tfarina42834112016-09-22 13:38:202937 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012938 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462939
2940 rv = callback.WaitForResult();
2941 EXPECT_EQ(0, rv);
2942
Ryan Sleevib8d7ea02018-05-07 20:01:012943 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162944 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012945 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162946 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192947
bnc691fda62016-08-12 00:43:162948 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522949 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582950 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462951}
2952
[email protected]2d2697f92009-02-18 21:00:322953// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2954// connection.
bncd16676a2016-07-20 16:23:012955TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182956 // On the second pass, the body read of the auth challenge is synchronous, so
2957 // IsConnectedAndIdle returns false. The socket should still be drained and
2958 // reused. See http://crbug.com/544255.
2959 for (int i = 0; i < 2; ++i) {
2960 HttpRequestInfo request;
2961 request.method = "GET";
2962 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:102963 request.traffic_annotation =
2964 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322965
mmenkecc2298e2015-12-07 18:20:182966 TestNetLog log;
2967 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092968 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272969
mmenkecc2298e2015-12-07 18:20:182970 MockWrite data_writes[] = {
2971 MockWrite(ASYNC, 0,
2972 "GET / HTTP/1.1\r\n"
2973 "Host: www.example.org\r\n"
2974 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322975
bnc691fda62016-08-12 00:43:162976 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182977 // be issuing -- the final header line contains the credentials.
2978 MockWrite(ASYNC, 6,
2979 "GET / HTTP/1.1\r\n"
2980 "Host: www.example.org\r\n"
2981 "Connection: keep-alive\r\n"
2982 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2983 };
[email protected]2d2697f92009-02-18 21:00:322984
mmenkecc2298e2015-12-07 18:20:182985 MockRead data_reads[] = {
2986 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2987 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2988 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2989 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2990 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322991
mmenkecc2298e2015-12-07 18:20:182992 // Lastly, the server responds with the actual content.
2993 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2994 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2995 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2996 MockRead(ASYNC, 10, "Hello"),
2997 };
[email protected]2d2697f92009-02-18 21:00:322998
Ryan Sleevib8d7ea02018-05-07 20:01:012999 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:183000 data.set_busy_before_sync_reads(true);
3001 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:463002
mmenkecc2298e2015-12-07 18:20:183003 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323004
bnc691fda62016-08-12 00:43:163005 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203006 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013007 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323008
mmenkecc2298e2015-12-07 18:20:183009 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:163010 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:183011 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:323012
bnc691fda62016-08-12 00:43:163013 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183014 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583015 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323016
mmenkecc2298e2015-12-07 18:20:183017 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:253018
bnc691fda62016-08-12 00:43:163019 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3020 callback2.callback());
robpercival214763f2016-07-01 23:27:013021 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323022
mmenkecc2298e2015-12-07 18:20:183023 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:163024 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:183025 TestLoadTimingReused(load_timing_info2);
3026 // The load timing after restart should have the same socket ID, and times
3027 // those of the first load timing.
3028 EXPECT_LE(load_timing_info1.receive_headers_end,
3029 load_timing_info2.send_start);
3030 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:323031
bnc691fda62016-08-12 00:43:163032 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183033 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583034 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:183035 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323036
mmenkecc2298e2015-12-07 18:20:183037 std::string response_data;
bnc691fda62016-08-12 00:43:163038 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:323039
Ryan Sleevib8d7ea02018-05-07 20:01:013040 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163041 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013042 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163043 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:183044 }
[email protected]2d2697f92009-02-18 21:00:323045}
3046
3047// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3048// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:013049TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:423050 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323051 request.method = "GET";
bncce36dca22015-04-21 22:11:233052 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103053 request.traffic_annotation =
3054 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323055
danakj1fd259a02016-04-16 03:17:093056 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273057
[email protected]2d2697f92009-02-18 21:00:323058 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163059 MockWrite("GET / HTTP/1.1\r\n"
3060 "Host: www.example.org\r\n"
3061 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323062
bnc691fda62016-08-12 00:43:163063 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233064 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163065 MockWrite("GET / HTTP/1.1\r\n"
3066 "Host: www.example.org\r\n"
3067 "Connection: keep-alive\r\n"
3068 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323069 };
3070
[email protected]2d2697f92009-02-18 21:00:323071 MockRead data_reads1[] = {
3072 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3073 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313074 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323075
3076 // Lastly, the server responds with the actual content.
3077 MockRead("HTTP/1.1 200 OK\r\n"),
3078 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503079 MockRead("Content-Length: 5\r\n\r\n"),
3080 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323081 };
3082
[email protected]2d0a4f92011-05-05 16:38:463083 // An incorrect reconnect would cause this to be read.
3084 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063085 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463086 };
3087
Ryan Sleevib8d7ea02018-05-07 20:01:013088 StaticSocketDataProvider data1(data_reads1, data_writes1);
3089 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073090 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3091 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323092
[email protected]49639fa2011-12-20 23:22:413093 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323094
bnc691fda62016-08-12 00:43:163095 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203096 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013097 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323098
3099 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013100 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323101
bnc691fda62016-08-12 00:43:163102 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523103 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583104 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323105
[email protected]49639fa2011-12-20 23:22:413106 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323107
bnc691fda62016-08-12 00:43:163108 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013109 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323110
3111 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013112 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323113
bnc691fda62016-08-12 00:43:163114 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523115 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583116 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503117 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323118}
3119
3120// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3121// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013122TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423123 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323124 request.method = "GET";
bncce36dca22015-04-21 22:11:233125 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103126 request.traffic_annotation =
3127 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323128
danakj1fd259a02016-04-16 03:17:093129 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273130
[email protected]2d2697f92009-02-18 21:00:323131 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163132 MockWrite("GET / HTTP/1.1\r\n"
3133 "Host: www.example.org\r\n"
3134 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323135
bnc691fda62016-08-12 00:43:163136 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233137 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163138 MockWrite("GET / HTTP/1.1\r\n"
3139 "Host: www.example.org\r\n"
3140 "Connection: keep-alive\r\n"
3141 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323142 };
3143
3144 // Respond with 5 kb of response body.
3145 std::string large_body_string("Unauthorized");
3146 large_body_string.append(5 * 1024, ' ');
3147 large_body_string.append("\r\n");
3148
3149 MockRead data_reads1[] = {
3150 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3151 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3152 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3153 // 5134 = 12 + 5 * 1024 + 2
3154 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063155 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323156
3157 // Lastly, the server responds with the actual content.
3158 MockRead("HTTP/1.1 200 OK\r\n"),
3159 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503160 MockRead("Content-Length: 5\r\n\r\n"),
3161 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323162 };
3163
[email protected]2d0a4f92011-05-05 16:38:463164 // An incorrect reconnect would cause this to be read.
3165 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063166 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463167 };
3168
Ryan Sleevib8d7ea02018-05-07 20:01:013169 StaticSocketDataProvider data1(data_reads1, data_writes1);
3170 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073171 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3172 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323173
[email protected]49639fa2011-12-20 23:22:413174 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323175
bnc691fda62016-08-12 00:43:163176 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203177 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013178 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323179
3180 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013181 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323182
bnc691fda62016-08-12 00:43:163183 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523184 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583185 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323186
[email protected]49639fa2011-12-20 23:22:413187 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323188
bnc691fda62016-08-12 00:43:163189 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013190 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323191
3192 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013193 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323194
bnc691fda62016-08-12 00:43:163195 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523196 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583197 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503198 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323199}
3200
3201// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313202// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013203TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313204 HttpRequestInfo request;
3205 request.method = "GET";
bncce36dca22015-04-21 22:11:233206 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103207 request.traffic_annotation =
3208 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313209
danakj1fd259a02016-04-16 03:17:093210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273211
[email protected]11203f012009-11-12 23:02:313212 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233213 MockWrite(
3214 "GET / HTTP/1.1\r\n"
3215 "Host: www.example.org\r\n"
3216 "Connection: keep-alive\r\n\r\n"),
3217 // This simulates the seemingly successful write to a closed connection
3218 // if the bug is not fixed.
3219 MockWrite(
3220 "GET / HTTP/1.1\r\n"
3221 "Host: www.example.org\r\n"
3222 "Connection: keep-alive\r\n"
3223 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313224 };
3225
3226 MockRead data_reads1[] = {
3227 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3228 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3229 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3230 MockRead("Content-Length: 14\r\n\r\n"),
3231 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063232 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313233 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063234 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313235 };
3236
bnc691fda62016-08-12 00:43:163237 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313238 // be issuing -- the final header line contains the credentials.
3239 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233240 MockWrite(
3241 "GET / HTTP/1.1\r\n"
3242 "Host: www.example.org\r\n"
3243 "Connection: keep-alive\r\n"
3244 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313245 };
3246
3247 // Lastly, the server responds with the actual content.
3248 MockRead data_reads2[] = {
3249 MockRead("HTTP/1.1 200 OK\r\n"),
3250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503251 MockRead("Content-Length: 5\r\n\r\n"),
3252 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313253 };
3254
Ryan Sleevib8d7ea02018-05-07 20:01:013255 StaticSocketDataProvider data1(data_reads1, data_writes1);
3256 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073257 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3258 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313259
[email protected]49639fa2011-12-20 23:22:413260 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313261
bnc691fda62016-08-12 00:43:163262 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203263 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313265
3266 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013267 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313268
bnc691fda62016-08-12 00:43:163269 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523270 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583271 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313272
[email protected]49639fa2011-12-20 23:22:413273 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313274
bnc691fda62016-08-12 00:43:163275 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013276 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313277
3278 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013279 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313280
bnc691fda62016-08-12 00:43:163281 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523282 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583283 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503284 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313285}
3286
[email protected]394816e92010-08-03 07:38:593287// Test the request-challenge-retry sequence for basic auth, over a connection
3288// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013289TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013290 HttpRequestInfo request;
3291 request.method = "GET";
bncce36dca22015-04-21 22:11:233292 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013293 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293294 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103295 request.traffic_annotation =
3296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013297
3298 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593299 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493300 ProxyResolutionService::CreateFixedFromPacResult(
3301 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513302 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013303 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013305
3306 // Since we have proxy, should try to establish tunnel.
3307 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543308 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173309 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543310 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013311 };
3312
mmenkee71e15332015-10-07 16:39:543313 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013314 // connection.
3315 MockRead data_reads1[] = {
3316 // No credentials.
3317 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3318 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543319 };
ttuttle34f63b52015-03-05 04:33:013320
mmenkee71e15332015-10-07 16:39:543321 // Since the first connection couldn't be reused, need to establish another
3322 // once given credentials.
3323 MockWrite data_writes2[] = {
3324 // After calling trans->RestartWithAuth(), this is the request we should
3325 // be issuing -- the final header line contains the credentials.
3326 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173327 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543328 "Proxy-Connection: keep-alive\r\n"
3329 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3330
3331 MockWrite("GET / HTTP/1.1\r\n"
3332 "Host: www.example.org\r\n"
3333 "Connection: keep-alive\r\n\r\n"),
3334 };
3335
3336 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013337 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3338
3339 MockRead("HTTP/1.1 200 OK\r\n"),
3340 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3341 MockRead("Content-Length: 5\r\n\r\n"),
3342 MockRead(SYNCHRONOUS, "hello"),
3343 };
3344
Ryan Sleevib8d7ea02018-05-07 20:01:013345 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013346 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013347 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543348 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013349 SSLSocketDataProvider ssl(ASYNC, OK);
3350 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3351
3352 TestCompletionCallback callback1;
3353
bnc87dcefc2017-05-25 12:47:583354 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193355 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013356
3357 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013359
3360 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013361 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:463362 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:013363 log.GetEntries(&entries);
3364 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003365 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3366 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013367 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003368 entries, pos,
3369 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3370 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013371
3372 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523373 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013374 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523375 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013376 EXPECT_EQ(407, response->headers->response_code());
3377 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583378 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013379
3380 LoadTimingInfo load_timing_info;
3381 // CONNECT requests and responses are handled at the connect job level, so
3382 // the transaction does not yet have a connection.
3383 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3384
3385 TestCompletionCallback callback2;
3386
3387 rv =
3388 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013389 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013390
3391 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013392 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013393
3394 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523395 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013396
3397 EXPECT_TRUE(response->headers->IsKeepAlive());
3398 EXPECT_EQ(200, response->headers->response_code());
3399 EXPECT_EQ(5, response->headers->GetContentLength());
3400 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3401
3402 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583403 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013404
3405 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3406 TestLoadTimingNotReusedWithPac(load_timing_info,
3407 CONNECT_TIMING_HAS_SSL_TIMES);
3408
3409 trans.reset();
3410 session->CloseAllConnections();
3411}
3412
3413// Test the request-challenge-retry sequence for basic auth, over a connection
3414// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013415TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593416 HttpRequestInfo request;
3417 request.method = "GET";
bncce36dca22015-04-21 22:11:233418 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593419 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293420 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103421 request.traffic_annotation =
3422 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593423
[email protected]cb9bf6ca2011-01-28 13:15:273424 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593425 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493426 ProxyResolutionService::CreateFixedFromPacResult(
3427 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513428 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073429 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093430 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273431
[email protected]394816e92010-08-03 07:38:593432 // Since we have proxy, should try to establish tunnel.
3433 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543434 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173435 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543436 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113437 };
3438
mmenkee71e15332015-10-07 16:39:543439 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083440 // connection.
3441 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543442 // No credentials.
3443 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3444 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3445 MockRead("Proxy-Connection: close\r\n\r\n"),
3446 };
mmenkee0b5c882015-08-26 20:29:113447
mmenkee71e15332015-10-07 16:39:543448 MockWrite data_writes2[] = {
3449 // After calling trans->RestartWithAuth(), this is the request we should
3450 // be issuing -- the final header line contains the credentials.
3451 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173452 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543453 "Proxy-Connection: keep-alive\r\n"
3454 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083455
mmenkee71e15332015-10-07 16:39:543456 MockWrite("GET / HTTP/1.1\r\n"
3457 "Host: www.example.org\r\n"
3458 "Connection: keep-alive\r\n\r\n"),
3459 };
3460
3461 MockRead data_reads2[] = {
3462 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3463
3464 MockRead("HTTP/1.1 200 OK\r\n"),
3465 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3466 MockRead("Content-Length: 5\r\n\r\n"),
3467 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593468 };
3469
Ryan Sleevib8d7ea02018-05-07 20:01:013470 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073471 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013472 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543473 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063474 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593476
[email protected]49639fa2011-12-20 23:22:413477 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593478
bnc87dcefc2017-05-25 12:47:583479 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193480 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503481
[email protected]49639fa2011-12-20 23:22:413482 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013483 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593484
3485 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013486 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:463487 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403488 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:593489 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003490 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3491 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593492 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403493 entries, pos,
mikecirone8b85c432016-09-08 19:11:003494 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3495 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593496
3497 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523498 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013499 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523500 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593501 EXPECT_EQ(407, response->headers->response_code());
3502 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583503 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593504
[email protected]029c83b62013-01-24 05:28:203505 LoadTimingInfo load_timing_info;
3506 // CONNECT requests and responses are handled at the connect job level, so
3507 // the transaction does not yet have a connection.
3508 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3509
[email protected]49639fa2011-12-20 23:22:413510 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593511
[email protected]49639fa2011-12-20 23:22:413512 rv = trans->RestartWithAuth(
3513 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013514 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593515
3516 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013517 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593518
3519 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523520 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593521
3522 EXPECT_TRUE(response->headers->IsKeepAlive());
3523 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503524 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593525 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3526
3527 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583528 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503529
[email protected]029c83b62013-01-24 05:28:203530 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3531 TestLoadTimingNotReusedWithPac(load_timing_info,
3532 CONNECT_TIMING_HAS_SSL_TIMES);
3533
[email protected]0b0bf032010-09-21 18:08:503534 trans.reset();
[email protected]102e27c2011-02-23 01:01:313535 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593536}
3537
[email protected]11203f012009-11-12 23:02:313538// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013539// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013540TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233541 // On the second pass, the body read of the auth challenge is synchronous, so
3542 // IsConnectedAndIdle returns false. The socket should still be drained and
3543 // reused. See http://crbug.com/544255.
3544 for (int i = 0; i < 2; ++i) {
3545 HttpRequestInfo request;
3546 request.method = "GET";
3547 request.url = GURL("https://www.example.org/");
3548 // Ensure that proxy authentication is attempted even
3549 // when the no authentication data flag is set.
3550 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103551 request.traffic_annotation =
3552 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013553
mmenked39192ee2015-12-09 00:57:233554 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593555 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493556 ProxyResolutionService::CreateFixed("myproxy:70",
3557 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233558 BoundTestNetLog log;
3559 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093560 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013561
bnc691fda62016-08-12 00:43:163562 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013563
mmenked39192ee2015-12-09 00:57:233564 // Since we have proxy, should try to establish tunnel.
3565 MockWrite data_writes1[] = {
3566 MockWrite(ASYNC, 0,
3567 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3568 "Host: www.example.org:443\r\n"
3569 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013570
bnc691fda62016-08-12 00:43:163571 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233572 // be issuing -- the final header line contains the credentials.
3573 MockWrite(ASYNC, 3,
3574 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3575 "Host: www.example.org:443\r\n"
3576 "Proxy-Connection: keep-alive\r\n"
3577 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3578 };
ttuttle34f63b52015-03-05 04:33:013579
mmenked39192ee2015-12-09 00:57:233580 // The proxy responds to the connect with a 407, using a persistent
3581 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3582 MockRead data_reads1[] = {
3583 // No credentials.
3584 MockRead(ASYNC, 1,
3585 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3586 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3587 "Proxy-Connection: keep-alive\r\n"
3588 "Content-Length: 10\r\n\r\n"),
3589 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013590
mmenked39192ee2015-12-09 00:57:233591 // Wrong credentials (wrong password).
3592 MockRead(ASYNC, 4,
3593 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3594 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3595 "Proxy-Connection: keep-alive\r\n"
3596 "Content-Length: 10\r\n\r\n"),
3597 // No response body because the test stops reading here.
3598 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3599 };
ttuttle34f63b52015-03-05 04:33:013600
Ryan Sleevib8d7ea02018-05-07 20:01:013601 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233602 data1.set_busy_before_sync_reads(true);
3603 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013604
mmenked39192ee2015-12-09 00:57:233605 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013606
bnc691fda62016-08-12 00:43:163607 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013608 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013609
mmenked39192ee2015-12-09 00:57:233610 TestNetLogEntry::List entries;
3611 log.GetEntries(&entries);
3612 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003613 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3614 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233615 ExpectLogContainsSomewhere(
3616 entries, pos,
mikecirone8b85c432016-09-08 19:11:003617 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3618 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013619
bnc691fda62016-08-12 00:43:163620 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233621 ASSERT_TRUE(response);
3622 ASSERT_TRUE(response->headers);
3623 EXPECT_TRUE(response->headers->IsKeepAlive());
3624 EXPECT_EQ(407, response->headers->response_code());
3625 EXPECT_EQ(10, response->headers->GetContentLength());
3626 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583627 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013628
mmenked39192ee2015-12-09 00:57:233629 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013630
mmenked39192ee2015-12-09 00:57:233631 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163632 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3633 callback2.callback());
robpercival214763f2016-07-01 23:27:013634 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013635
bnc691fda62016-08-12 00:43:163636 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233637 ASSERT_TRUE(response);
3638 ASSERT_TRUE(response->headers);
3639 EXPECT_TRUE(response->headers->IsKeepAlive());
3640 EXPECT_EQ(407, response->headers->response_code());
3641 EXPECT_EQ(10, response->headers->GetContentLength());
3642 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583643 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013644
mmenked39192ee2015-12-09 00:57:233645 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3646 // out of scope.
3647 session->CloseAllConnections();
3648 }
ttuttle34f63b52015-03-05 04:33:013649}
3650
3651// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3652// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013653TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233654 // On the second pass, the body read of the auth challenge is synchronous, so
3655 // IsConnectedAndIdle returns false. The socket should still be drained and
3656 // reused. See http://crbug.com/544255.
3657 for (int i = 0; i < 2; ++i) {
3658 HttpRequestInfo request;
3659 request.method = "GET";
3660 request.url = GURL("https://www.example.org/");
3661 // Ensure that proxy authentication is attempted even
3662 // when the no authentication data flag is set.
3663 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103664 request.traffic_annotation =
3665 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233666
3667 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593668 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493669 ProxyResolutionService::CreateFixed("myproxy:70",
3670 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233671 BoundTestNetLog log;
3672 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093673 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233674
bnc691fda62016-08-12 00:43:163675 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233676
3677 // Since we have proxy, should try to establish tunnel.
3678 MockWrite data_writes1[] = {
3679 MockWrite(ASYNC, 0,
3680 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3681 "Host: www.example.org:443\r\n"
3682 "Proxy-Connection: keep-alive\r\n\r\n"),
3683
bnc691fda62016-08-12 00:43:163684 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233685 // be issuing -- the final header line contains the credentials.
3686 MockWrite(ASYNC, 3,
3687 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3688 "Host: www.example.org:443\r\n"
3689 "Proxy-Connection: keep-alive\r\n"
3690 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3691 };
3692
3693 // The proxy responds to the connect with a 407, using a persistent
3694 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3695 MockRead data_reads1[] = {
3696 // No credentials.
3697 MockRead(ASYNC, 1,
3698 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3699 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3700 "Content-Length: 10\r\n\r\n"),
3701 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3702
3703 // Wrong credentials (wrong password).
3704 MockRead(ASYNC, 4,
3705 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3706 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3707 "Content-Length: 10\r\n\r\n"),
3708 // No response body because the test stops reading here.
3709 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3710 };
3711
Ryan Sleevib8d7ea02018-05-07 20:01:013712 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233713 data1.set_busy_before_sync_reads(true);
3714 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3715
3716 TestCompletionCallback callback1;
3717
bnc691fda62016-08-12 00:43:163718 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013719 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233720
3721 TestNetLogEntry::List entries;
3722 log.GetEntries(&entries);
3723 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003724 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3725 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233726 ExpectLogContainsSomewhere(
3727 entries, pos,
mikecirone8b85c432016-09-08 19:11:003728 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3729 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233730
bnc691fda62016-08-12 00:43:163731 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233732 ASSERT_TRUE(response);
3733 ASSERT_TRUE(response->headers);
3734 EXPECT_TRUE(response->headers->IsKeepAlive());
3735 EXPECT_EQ(407, response->headers->response_code());
3736 EXPECT_EQ(10, response->headers->GetContentLength());
3737 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583738 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503739 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233740
3741 TestCompletionCallback callback2;
3742
3743 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163744 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3745 callback2.callback());
robpercival214763f2016-07-01 23:27:013746 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233747
bnc691fda62016-08-12 00:43:163748 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233749 ASSERT_TRUE(response);
3750 ASSERT_TRUE(response->headers);
3751 EXPECT_TRUE(response->headers->IsKeepAlive());
3752 EXPECT_EQ(407, response->headers->response_code());
3753 EXPECT_EQ(10, response->headers->GetContentLength());
3754 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583755 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503756 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233757
3758 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3759 // out of scope.
3760 session->CloseAllConnections();
3761 }
3762}
3763
3764// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3765// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3766// the case the server sends extra data on the original socket, so it can't be
3767// reused.
bncd16676a2016-07-20 16:23:013768TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273769 HttpRequestInfo request;
3770 request.method = "GET";
bncce36dca22015-04-21 22:11:233771 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273772 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293773 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103774 request.traffic_annotation =
3775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273776
[email protected]2d2697f92009-02-18 21:00:323777 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593778 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493779 ProxyResolutionService::CreateFixedFromPacResult(
3780 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513781 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073782 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093783 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323784
[email protected]2d2697f92009-02-18 21:00:323785 // Since we have proxy, should try to establish tunnel.
3786 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233787 MockWrite(ASYNC, 0,
3788 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173789 "Host: www.example.org:443\r\n"
3790 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233791 };
[email protected]2d2697f92009-02-18 21:00:323792
mmenked39192ee2015-12-09 00:57:233793 // The proxy responds to the connect with a 407, using a persistent, but sends
3794 // extra data, so the socket cannot be reused.
3795 MockRead data_reads1[] = {
3796 // No credentials.
3797 MockRead(ASYNC, 1,
3798 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3799 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3800 "Content-Length: 10\r\n\r\n"),
3801 MockRead(SYNCHRONOUS, 2, "0123456789"),
3802 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3803 };
3804
3805 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233806 // After calling trans->RestartWithAuth(), this is the request we should
3807 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233808 MockWrite(ASYNC, 0,
3809 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173810 "Host: www.example.org:443\r\n"
3811 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233812 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3813
3814 MockWrite(ASYNC, 2,
3815 "GET / HTTP/1.1\r\n"
3816 "Host: www.example.org\r\n"
3817 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323818 };
3819
mmenked39192ee2015-12-09 00:57:233820 MockRead data_reads2[] = {
3821 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323822
mmenked39192ee2015-12-09 00:57:233823 MockRead(ASYNC, 3,
3824 "HTTP/1.1 200 OK\r\n"
3825 "Content-Type: text/html; charset=iso-8859-1\r\n"
3826 "Content-Length: 5\r\n\r\n"),
3827 // No response body because the test stops reading here.
3828 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323829 };
3830
Ryan Sleevib8d7ea02018-05-07 20:01:013831 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233832 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073833 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013834 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233835 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3836 SSLSocketDataProvider ssl(ASYNC, OK);
3837 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323838
[email protected]49639fa2011-12-20 23:22:413839 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323840
bnc87dcefc2017-05-25 12:47:583841 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193842 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323843
mmenked39192ee2015-12-09 00:57:233844 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013845 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233846
mmenke43758e62015-05-04 21:09:463847 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403848 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:393849 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003850 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3851 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393852 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403853 entries, pos,
mikecirone8b85c432016-09-08 19:11:003854 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3855 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323856
[email protected]1c773ea12009-04-28 19:58:423857 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243858 ASSERT_TRUE(response);
3859 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323860 EXPECT_TRUE(response->headers->IsKeepAlive());
3861 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423862 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583863 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323864
mmenked39192ee2015-12-09 00:57:233865 LoadTimingInfo load_timing_info;
3866 // CONNECT requests and responses are handled at the connect job level, so
3867 // the transaction does not yet have a connection.
3868 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3869
[email protected]49639fa2011-12-20 23:22:413870 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323871
mmenked39192ee2015-12-09 00:57:233872 rv =
3873 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013874 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323875
[email protected]2d2697f92009-02-18 21:00:323876 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233877 EXPECT_EQ(200, response->headers->response_code());
3878 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423879 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133880
mmenked39192ee2015-12-09 00:57:233881 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583882 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233883
3884 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3885 TestLoadTimingNotReusedWithPac(load_timing_info,
3886 CONNECT_TIMING_HAS_SSL_TIMES);
3887
3888 trans.reset();
[email protected]102e27c2011-02-23 01:01:313889 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323890}
3891
mmenkee71e15332015-10-07 16:39:543892// Test the case a proxy closes a socket while the challenge body is being
3893// drained.
bncd16676a2016-07-20 16:23:013894TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543895 HttpRequestInfo request;
3896 request.method = "GET";
3897 request.url = GURL("https://www.example.org/");
3898 // Ensure that proxy authentication is attempted even
3899 // when the no authentication data flag is set.
3900 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:103901 request.traffic_annotation =
3902 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543903
3904 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493905 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3906 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093907 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543908
bnc691fda62016-08-12 00:43:163909 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543910
3911 // Since we have proxy, should try to establish tunnel.
3912 MockWrite data_writes1[] = {
3913 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173914 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543915 "Proxy-Connection: keep-alive\r\n\r\n"),
3916 };
3917
3918 // The proxy responds to the connect with a 407, using a persistent
3919 // connection.
3920 MockRead data_reads1[] = {
3921 // No credentials.
3922 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3923 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3924 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3925 // Server hands up in the middle of the body.
3926 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3927 };
3928
3929 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163930 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543931 // be issuing -- the final header line contains the credentials.
3932 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173933 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543934 "Proxy-Connection: keep-alive\r\n"
3935 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3936
3937 MockWrite("GET / HTTP/1.1\r\n"
3938 "Host: www.example.org\r\n"
3939 "Connection: keep-alive\r\n\r\n"),
3940 };
3941
3942 MockRead data_reads2[] = {
3943 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3944
3945 MockRead("HTTP/1.1 200 OK\r\n"),
3946 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3947 MockRead("Content-Length: 5\r\n\r\n"),
3948 MockRead(SYNCHRONOUS, "hello"),
3949 };
3950
Ryan Sleevib8d7ea02018-05-07 20:01:013951 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543952 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013953 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543954 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3955 SSLSocketDataProvider ssl(ASYNC, OK);
3956 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3957
3958 TestCompletionCallback callback;
3959
tfarina42834112016-09-22 13:38:203960 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013961 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543962
bnc691fda62016-08-12 00:43:163963 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543964 ASSERT_TRUE(response);
3965 ASSERT_TRUE(response->headers);
3966 EXPECT_TRUE(response->headers->IsKeepAlive());
3967 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583968 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543969
bnc691fda62016-08-12 00:43:163970 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013971 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543972
bnc691fda62016-08-12 00:43:163973 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543974 ASSERT_TRUE(response);
3975 ASSERT_TRUE(response->headers);
3976 EXPECT_TRUE(response->headers->IsKeepAlive());
3977 EXPECT_EQ(200, response->headers->response_code());
3978 std::string body;
bnc691fda62016-08-12 00:43:163979 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543980 EXPECT_EQ("hello", body);
3981}
3982
[email protected]a8e9b162009-03-12 00:06:443983// Test that we don't read the response body when we fail to establish a tunnel,
3984// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013985TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273986 HttpRequestInfo request;
3987 request.method = "GET";
bncce36dca22015-04-21 22:11:233988 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:103989 request.traffic_annotation =
3990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273991
[email protected]a8e9b162009-03-12 00:06:443992 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493993 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3994 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443995
danakj1fd259a02016-04-16 03:17:093996 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443997
bnc691fda62016-08-12 00:43:163998 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443999
[email protected]a8e9b162009-03-12 00:06:444000 // Since we have proxy, should try to establish tunnel.
4001 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174002 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4003 "Host: www.example.org:443\r\n"
4004 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:444005 };
4006
4007 // The proxy responds to the connect with a 407.
4008 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:244009 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4010 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4011 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234012 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:244013 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:444014 };
4015
Ryan Sleevib8d7ea02018-05-07 20:01:014016 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:074017 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:444018
[email protected]49639fa2011-12-20 23:22:414019 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:444020
tfarina42834112016-09-22 13:38:204021 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014022 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:444023
4024 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014025 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:444026
bnc691fda62016-08-12 00:43:164027 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244028 ASSERT_TRUE(response);
4029 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:444030 EXPECT_TRUE(response->headers->IsKeepAlive());
4031 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424032 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:444033
4034 std::string response_data;
bnc691fda62016-08-12 00:43:164035 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014036 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:184037
4038 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:314039 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:444040}
4041
ttuttle7933c112015-01-06 00:55:244042// Test that we don't pass extraneous headers from the proxy's response to the
4043// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014044TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244045 HttpRequestInfo request;
4046 request.method = "GET";
bncce36dca22015-04-21 22:11:234047 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104048 request.traffic_annotation =
4049 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244050
4051 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:494052 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4053 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244054
danakj1fd259a02016-04-16 03:17:094055 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244056
bnc691fda62016-08-12 00:43:164057 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244058
4059 // Since we have proxy, should try to establish tunnel.
4060 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174061 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4062 "Host: www.example.org:443\r\n"
4063 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244064 };
4065
4066 // The proxy responds to the connect with a 407.
4067 MockRead data_reads[] = {
4068 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4069 MockRead("X-Foo: bar\r\n"),
4070 MockRead("Set-Cookie: foo=bar\r\n"),
4071 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4072 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234073 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244074 };
4075
Ryan Sleevib8d7ea02018-05-07 20:01:014076 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244077 session_deps_.socket_factory->AddSocketDataProvider(&data);
4078
4079 TestCompletionCallback callback;
4080
tfarina42834112016-09-22 13:38:204081 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014082 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244083
4084 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014085 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244086
bnc691fda62016-08-12 00:43:164087 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244088 ASSERT_TRUE(response);
4089 ASSERT_TRUE(response->headers);
4090 EXPECT_TRUE(response->headers->IsKeepAlive());
4091 EXPECT_EQ(407, response->headers->response_code());
4092 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4093 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4094 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4095
4096 std::string response_data;
bnc691fda62016-08-12 00:43:164097 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014098 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244099
4100 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4101 session->CloseAllConnections();
4102}
4103
[email protected]8fdbcd22010-05-05 02:54:524104// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4105// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014106TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524107 HttpRequestInfo request;
4108 request.method = "GET";
bncce36dca22015-04-21 22:11:234109 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104110 request.traffic_annotation =
4111 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524112
[email protected]cb9bf6ca2011-01-28 13:15:274113 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094114 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164115 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274116
[email protected]8fdbcd22010-05-05 02:54:524117 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234118 MockWrite(
4119 "GET / HTTP/1.1\r\n"
4120 "Host: www.example.org\r\n"
4121 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524122 };
4123
4124 MockRead data_reads1[] = {
4125 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4126 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4127 // Large content-length -- won't matter, as connection will be reset.
4128 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064129 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524130 };
4131
Ryan Sleevib8d7ea02018-05-07 20:01:014132 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074133 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524134
[email protected]49639fa2011-12-20 23:22:414135 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524136
tfarina42834112016-09-22 13:38:204137 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014138 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524139
4140 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014141 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524142}
4143
[email protected]7a67a8152010-11-05 18:31:104144// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4145// through a non-authenticating proxy. The request should fail with
4146// ERR_UNEXPECTED_PROXY_AUTH.
4147// Note that it is impossible to detect if an HTTP server returns a 407 through
4148// a non-authenticating proxy - there is nothing to indicate whether the
4149// response came from the proxy or the server, so it is treated as if the proxy
4150// issued the challenge.
bncd16676a2016-07-20 16:23:014151TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274152 HttpRequestInfo request;
4153 request.method = "GET";
bncce36dca22015-04-21 22:11:234154 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104155 request.traffic_annotation =
4156 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274157
Ramin Halavatica8d5252018-03-12 05:33:494158 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4159 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514160 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074161 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094162 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104163
[email protected]7a67a8152010-11-05 18:31:104164 // Since we have proxy, should try to establish tunnel.
4165 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174166 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4167 "Host: www.example.org:443\r\n"
4168 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104169
rsleevidb16bb02015-11-12 23:47:174170 MockWrite("GET / HTTP/1.1\r\n"
4171 "Host: www.example.org\r\n"
4172 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104173 };
4174
4175 MockRead data_reads1[] = {
4176 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4177
4178 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4179 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4180 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064181 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104182 };
4183
Ryan Sleevib8d7ea02018-05-07 20:01:014184 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074185 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064186 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074187 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104188
[email protected]49639fa2011-12-20 23:22:414189 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104190
bnc691fda62016-08-12 00:43:164191 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104192
bnc691fda62016-08-12 00:43:164193 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104195
4196 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014197 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
mmenke43758e62015-05-04 21:09:464198 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:404199 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:104200 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004201 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4202 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104203 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404204 entries, pos,
mikecirone8b85c432016-09-08 19:11:004205 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4206 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104207}
[email protected]2df19bb2010-08-25 20:13:464208
mmenke2a1781d2015-10-07 19:25:334209// Test a proxy auth scheme that allows default credentials and a proxy server
4210// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014211TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334212 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4213 HttpRequestInfo request;
4214 request.method = "GET";
4215 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104216 request.traffic_annotation =
4217 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334218
4219 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594220 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494221 ProxyResolutionService::CreateFixedFromPacResult(
4222 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334223
Jeremy Roman0579ed62017-08-29 15:56:194224 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334225 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194226 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334227 mock_handler->set_allows_default_credentials(true);
4228 auth_handler_factory->AddMockHandler(mock_handler.release(),
4229 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484230 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334231
4232 // Add NetLog just so can verify load timing information gets a NetLog ID.
4233 NetLog net_log;
4234 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094235 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334236
4237 // Since we have proxy, should try to establish tunnel.
4238 MockWrite data_writes1[] = {
4239 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174240 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334241 "Proxy-Connection: keep-alive\r\n\r\n"),
4242 };
4243
4244 // The proxy responds to the connect with a 407, using a non-persistent
4245 // connection.
4246 MockRead data_reads1[] = {
4247 // No credentials.
4248 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4249 MockRead("Proxy-Authenticate: Mock\r\n"),
4250 MockRead("Proxy-Connection: close\r\n\r\n"),
4251 };
4252
4253 // Since the first connection couldn't be reused, need to establish another
4254 // once given credentials.
4255 MockWrite data_writes2[] = {
4256 // After calling trans->RestartWithAuth(), this is the request we should
4257 // be issuing -- the final header line contains the credentials.
4258 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174259 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334260 "Proxy-Connection: keep-alive\r\n"
4261 "Proxy-Authorization: auth_token\r\n\r\n"),
4262
4263 MockWrite("GET / HTTP/1.1\r\n"
4264 "Host: www.example.org\r\n"
4265 "Connection: keep-alive\r\n\r\n"),
4266 };
4267
4268 MockRead data_reads2[] = {
4269 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4270
4271 MockRead("HTTP/1.1 200 OK\r\n"),
4272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4273 MockRead("Content-Length: 5\r\n\r\n"),
4274 MockRead(SYNCHRONOUS, "hello"),
4275 };
4276
Ryan Sleevib8d7ea02018-05-07 20:01:014277 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334278 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014279 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334280 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4281 SSLSocketDataProvider ssl(ASYNC, OK);
4282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4283
bnc87dcefc2017-05-25 12:47:584284 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194285 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334286
4287 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204288 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014289 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334290
4291 const HttpResponseInfo* response = trans->GetResponseInfo();
4292 ASSERT_TRUE(response);
4293 ASSERT_TRUE(response->headers);
4294 EXPECT_FALSE(response->headers->IsKeepAlive());
4295 EXPECT_EQ(407, response->headers->response_code());
4296 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4297 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584298 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334299
4300 LoadTimingInfo load_timing_info;
4301 // CONNECT requests and responses are handled at the connect job level, so
4302 // the transaction does not yet have a connection.
4303 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4304
4305 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014306 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334307 response = trans->GetResponseInfo();
4308 ASSERT_TRUE(response);
4309 ASSERT_TRUE(response->headers);
4310 EXPECT_TRUE(response->headers->IsKeepAlive());
4311 EXPECT_EQ(200, response->headers->response_code());
4312 EXPECT_EQ(5, response->headers->GetContentLength());
4313 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4314
4315 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584316 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334317
4318 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4319 TestLoadTimingNotReusedWithPac(load_timing_info,
4320 CONNECT_TIMING_HAS_SSL_TIMES);
4321
4322 trans.reset();
4323 session->CloseAllConnections();
4324}
4325
4326// Test a proxy auth scheme that allows default credentials and a proxy server
4327// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014328TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334329 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4330 HttpRequestInfo request;
4331 request.method = "GET";
4332 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104333 request.traffic_annotation =
4334 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334335
4336 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594337 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494338 ProxyResolutionService::CreateFixedFromPacResult(
4339 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334340
Jeremy Roman0579ed62017-08-29 15:56:194341 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334342 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194343 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334344 mock_handler->set_allows_default_credentials(true);
4345 auth_handler_factory->AddMockHandler(mock_handler.release(),
4346 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484347 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334348
4349 // Add NetLog just so can verify load timing information gets a NetLog ID.
4350 NetLog net_log;
4351 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094352 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334353
4354 // Should try to establish tunnel.
4355 MockWrite data_writes1[] = {
4356 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174357 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334358 "Proxy-Connection: keep-alive\r\n\r\n"),
4359
4360 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174361 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334362 "Proxy-Connection: keep-alive\r\n"
4363 "Proxy-Authorization: auth_token\r\n\r\n"),
4364 };
4365
4366 // The proxy responds to the connect with a 407, using a non-persistent
4367 // connection.
4368 MockRead data_reads1[] = {
4369 // No credentials.
4370 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4371 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4372 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4373 };
4374
4375 // Since the first connection was closed, need to establish another once given
4376 // credentials.
4377 MockWrite data_writes2[] = {
4378 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174379 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334380 "Proxy-Connection: keep-alive\r\n"
4381 "Proxy-Authorization: auth_token\r\n\r\n"),
4382
4383 MockWrite("GET / HTTP/1.1\r\n"
4384 "Host: www.example.org\r\n"
4385 "Connection: keep-alive\r\n\r\n"),
4386 };
4387
4388 MockRead data_reads2[] = {
4389 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4390
4391 MockRead("HTTP/1.1 200 OK\r\n"),
4392 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4393 MockRead("Content-Length: 5\r\n\r\n"),
4394 MockRead(SYNCHRONOUS, "hello"),
4395 };
4396
Ryan Sleevib8d7ea02018-05-07 20:01:014397 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334398 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014399 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334400 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4401 SSLSocketDataProvider ssl(ASYNC, OK);
4402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4403
bnc87dcefc2017-05-25 12:47:584404 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194405 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334406
4407 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204408 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014409 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334410
4411 const HttpResponseInfo* response = trans->GetResponseInfo();
4412 ASSERT_TRUE(response);
4413 ASSERT_TRUE(response->headers);
4414 EXPECT_TRUE(response->headers->IsKeepAlive());
4415 EXPECT_EQ(407, response->headers->response_code());
4416 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4417 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584418 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334419
4420 LoadTimingInfo load_timing_info;
4421 // CONNECT requests and responses are handled at the connect job level, so
4422 // the transaction does not yet have a connection.
4423 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4424
4425 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014426 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334427
4428 response = trans->GetResponseInfo();
4429 ASSERT_TRUE(response);
4430 ASSERT_TRUE(response->headers);
4431 EXPECT_TRUE(response->headers->IsKeepAlive());
4432 EXPECT_EQ(200, response->headers->response_code());
4433 EXPECT_EQ(5, response->headers->GetContentLength());
4434 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4435
4436 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584437 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334438
4439 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4440 TestLoadTimingNotReusedWithPac(load_timing_info,
4441 CONNECT_TIMING_HAS_SSL_TIMES);
4442
4443 trans.reset();
4444 session->CloseAllConnections();
4445}
4446
4447// Test a proxy auth scheme that allows default credentials and a proxy server
4448// that hangs up when credentials are initially sent, and hangs up again when
4449// they are retried.
bncd16676a2016-07-20 16:23:014450TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334451 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
4452 HttpRequestInfo request;
4453 request.method = "GET";
4454 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104455 request.traffic_annotation =
4456 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334457
4458 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594459 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494460 ProxyResolutionService::CreateFixedFromPacResult(
4461 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334462
Jeremy Roman0579ed62017-08-29 15:56:194463 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334464 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194465 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334466 mock_handler->set_allows_default_credentials(true);
4467 auth_handler_factory->AddMockHandler(mock_handler.release(),
4468 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484469 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334470
4471 // Add NetLog just so can verify load timing information gets a NetLog ID.
4472 NetLog net_log;
4473 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094474 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334475
4476 // Should try to establish tunnel.
4477 MockWrite data_writes1[] = {
4478 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174479 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334480 "Proxy-Connection: keep-alive\r\n\r\n"),
4481
4482 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174483 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334484 "Proxy-Connection: keep-alive\r\n"
4485 "Proxy-Authorization: auth_token\r\n\r\n"),
4486 };
4487
4488 // The proxy responds to the connect with a 407, and then hangs up after the
4489 // second request is sent.
4490 MockRead data_reads1[] = {
4491 // No credentials.
4492 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4493 MockRead("Content-Length: 0\r\n"),
4494 MockRead("Proxy-Connection: keep-alive\r\n"),
4495 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4496 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4497 };
4498
4499 // HttpNetworkTransaction sees a reused connection that was closed with
4500 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
4501 // request.
4502 MockWrite data_writes2[] = {
4503 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174504 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334505 "Proxy-Connection: keep-alive\r\n\r\n"),
4506 };
4507
4508 // The proxy, having had more than enough of us, just hangs up.
4509 MockRead data_reads2[] = {
4510 // No credentials.
4511 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4512 };
4513
Ryan Sleevib8d7ea02018-05-07 20:01:014514 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334515 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014516 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334517 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4518
bnc87dcefc2017-05-25 12:47:584519 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194520 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334521
4522 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204523 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014524 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334525
4526 const HttpResponseInfo* response = trans->GetResponseInfo();
4527 ASSERT_TRUE(response);
4528 ASSERT_TRUE(response->headers);
4529 EXPECT_TRUE(response->headers->IsKeepAlive());
4530 EXPECT_EQ(407, response->headers->response_code());
4531 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4532 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584533 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334534
4535 LoadTimingInfo load_timing_info;
4536 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4537
4538 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014539 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:334540
4541 trans.reset();
4542 session->CloseAllConnections();
4543}
4544
Asanka Herathbc3f8f62018-11-16 23:08:304545// This test exercises an odd edge case where the proxy closes the connection
4546// after the authentication handshake is complete. Presumably this technique is
4547// used in lieu of returning a 403 or 5xx status code when the authentication
4548// succeeds, but the user is not authorized to connect to the destination
4549// server. There's no standard for what a proxy should do to indicate a blocked
4550// site.
4551TEST_F(HttpNetworkTransactionTest,
4552 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
4553 HttpRequestInfo request;
4554 request.method = "GET";
4555 request.url = GURL("https://www.example.org/");
4556 request.traffic_annotation =
4557 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4558
4559 // Configure against proxy server "myproxy:70".
4560 session_deps_.proxy_resolution_service =
4561 ProxyResolutionService::CreateFixedFromPacResult(
4562 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4563
Asanka Herathbc3f8f62018-11-16 23:08:304564 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
4565 auth_handler_factory->set_do_init_from_challenge(true);
4566
4567 // Create two mock AuthHandlers. This is because the transaction gets retried
4568 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
4569 // was a real network error.
4570 //
4571 // The handlers support both default and explicit credentials. The retry
4572 // mentioned above should be able to reuse the default identity. Thus there
4573 // should never be a need to prompt for explicit credentials.
4574 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
4575 mock_handler->set_allows_default_credentials(true);
4576 mock_handler->set_allows_explicit_credentials(true);
4577 mock_handler->set_connection_based(true);
4578 auth_handler_factory->AddMockHandler(mock_handler.release(),
4579 HttpAuth::AUTH_PROXY);
4580 mock_handler = std::make_unique<HttpAuthHandlerMock>();
4581 mock_handler->set_allows_default_credentials(true);
4582 mock_handler->set_allows_explicit_credentials(true);
4583 mock_handler->set_connection_based(true);
4584 auth_handler_factory->AddMockHandler(mock_handler.release(),
4585 HttpAuth::AUTH_PROXY);
4586 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4587
4588 NetLog net_log;
4589 session_deps_.net_log = &net_log;
4590 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4591
4592 // Data for both sockets.
4593 //
4594 // Writes are for the tunnel establishment attempts and the
4595 // authentication handshake.
4596 MockWrite data_writes1[] = {
4597 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4598 "Host: www.example.org:443\r\n"
4599 "Proxy-Connection: keep-alive\r\n\r\n"),
4600
4601 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4602 "Host: www.example.org:443\r\n"
4603 "Proxy-Connection: keep-alive\r\n"
4604 "Proxy-Authorization: auth_token\r\n\r\n"),
4605
4606 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4607 "Host: www.example.org:443\r\n"
4608 "Proxy-Connection: keep-alive\r\n"
4609 "Proxy-Authorization: auth_token\r\n\r\n"),
4610 };
4611
4612 // The server side of the authentication handshake. Note that the response to
4613 // the final CONNECT request is ERR_CONNECTION_CLOSED.
4614 MockRead data_reads1[] = {
4615 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4616 MockRead("Content-Length: 0\r\n"),
4617 MockRead("Proxy-Connection: keep-alive\r\n"),
4618 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4619
4620 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4621 MockRead("Content-Length: 0\r\n"),
4622 MockRead("Proxy-Connection: keep-alive\r\n"),
4623 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
4624
4625 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4626 };
4627
4628 StaticSocketDataProvider data1(data_reads1, data_writes1);
4629 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4630
4631 // The second socket is for the reconnection attempt. Data is identical to the
4632 // first attempt.
4633 StaticSocketDataProvider data2(data_reads1, data_writes1);
4634 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4635
4636 auto trans =
4637 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4638
4639 TestCompletionCallback callback;
4640 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4641
4642 // Two rounds per handshake. After one retry, the error is propagated up the
4643 // stack.
4644 for (int i = 0; i < 4; ++i) {
4645 EXPECT_THAT(callback.GetResult(rv), IsOk());
4646
4647 const HttpResponseInfo* response = trans->GetResponseInfo();
4648 ASSERT_TRUE(response);
4649 ASSERT_TRUE(response->headers);
4650 EXPECT_EQ(407, response->headers->response_code());
4651 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
4652
4653 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4654 }
4655
4656 // One shall be the number thou shalt retry, and the number of the retrying
4657 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
4658 // that thou then proceed to one. Three is right out. Once the number one,
4659 // being the first number, be reached, then lobbest thou thy
4660 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
4661 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
4662
4663 trans.reset();
4664 session->CloseAllConnections();
4665}
4666
mmenke2a1781d2015-10-07 19:25:334667// Test a proxy auth scheme that allows default credentials and a proxy server
4668// that hangs up when credentials are initially sent, and sends a challenge
4669// again they are retried.
bncd16676a2016-07-20 16:23:014670TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334671 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
4672 HttpRequestInfo request;
4673 request.method = "GET";
4674 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104675 request.traffic_annotation =
4676 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334677
4678 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594679 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494680 ProxyResolutionService::CreateFixedFromPacResult(
4681 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334682
Jeremy Roman0579ed62017-08-29 15:56:194683 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334684 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194685 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334686 mock_handler->set_allows_default_credentials(true);
4687 auth_handler_factory->AddMockHandler(mock_handler.release(),
4688 HttpAuth::AUTH_PROXY);
4689 // Add another handler for the second challenge. It supports default
4690 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194691 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334692 mock_handler->set_allows_default_credentials(true);
4693 auth_handler_factory->AddMockHandler(mock_handler.release(),
4694 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484695 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334696
4697 // Add NetLog just so can verify load timing information gets a NetLog ID.
4698 NetLog net_log;
4699 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094700 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334701
4702 // Should try to establish tunnel.
4703 MockWrite data_writes1[] = {
4704 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174705 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334706 "Proxy-Connection: keep-alive\r\n\r\n"),
4707 };
4708
4709 // The proxy responds to the connect with a 407, using a non-persistent
4710 // connection.
4711 MockRead data_reads1[] = {
4712 // No credentials.
4713 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4714 MockRead("Proxy-Authenticate: Mock\r\n"),
4715 MockRead("Proxy-Connection: close\r\n\r\n"),
4716 };
4717
4718 // Since the first connection was closed, need to establish another once given
4719 // credentials.
4720 MockWrite data_writes2[] = {
4721 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174722 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334723 "Proxy-Connection: keep-alive\r\n"
4724 "Proxy-Authorization: auth_token\r\n\r\n"),
4725 };
4726
4727 MockRead data_reads2[] = {
4728 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4729 MockRead("Proxy-Authenticate: Mock\r\n"),
4730 MockRead("Proxy-Connection: close\r\n\r\n"),
4731 };
4732
Ryan Sleevib8d7ea02018-05-07 20:01:014733 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334734 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014735 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334736 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4737 SSLSocketDataProvider ssl(ASYNC, OK);
4738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4739
bnc87dcefc2017-05-25 12:47:584740 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194741 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334742
4743 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204744 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014745 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334746
4747 const HttpResponseInfo* response = trans->GetResponseInfo();
4748 ASSERT_TRUE(response);
4749 ASSERT_TRUE(response->headers);
4750 EXPECT_EQ(407, response->headers->response_code());
4751 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4752 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584753 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334754
4755 LoadTimingInfo load_timing_info;
4756 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4757
4758 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014759 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334760 response = trans->GetResponseInfo();
4761 ASSERT_TRUE(response);
4762 ASSERT_TRUE(response->headers);
4763 EXPECT_EQ(407, response->headers->response_code());
4764 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584765 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334766
4767 trans.reset();
4768 session->CloseAllConnections();
4769}
4770
asankae2257db2016-10-11 22:03:164771// A more nuanced test than GenerateAuthToken test which asserts that
4772// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
4773// unnecessarily invalidated, and that if the server co-operates, the
4774// authentication handshake can continue with the same scheme but with a
4775// different identity.
4776TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
4777 HttpRequestInfo request;
4778 request.method = "GET";
4779 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:104780 request.traffic_annotation =
4781 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:164782
Jeremy Roman0579ed62017-08-29 15:56:194783 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:164784 auth_handler_factory->set_do_init_from_challenge(true);
4785
4786 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:194787 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164788 mock_handler->set_allows_default_credentials(true);
4789 mock_handler->set_allows_explicit_credentials(true);
4790 mock_handler->set_connection_based(true);
4791 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
4792 auth_handler_factory->AddMockHandler(mock_handler.release(),
4793 HttpAuth::AUTH_SERVER);
4794
4795 // Add another handler for the second challenge. It supports default
4796 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194797 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164798 mock_handler->set_allows_default_credentials(true);
4799 mock_handler->set_allows_explicit_credentials(true);
4800 mock_handler->set_connection_based(true);
4801 auth_handler_factory->AddMockHandler(mock_handler.release(),
4802 HttpAuth::AUTH_SERVER);
4803 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4804
4805 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4806
4807 MockWrite data_writes1[] = {
4808 MockWrite("GET / HTTP/1.1\r\n"
4809 "Host: www.example.org\r\n"
4810 "Connection: keep-alive\r\n\r\n"),
4811 };
4812
4813 MockRead data_reads1[] = {
4814 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4815 "WWW-Authenticate: Mock\r\n"
4816 "Connection: keep-alive\r\n\r\n"),
4817 };
4818
4819 // Identical to data_writes1[]. The AuthHandler encounters a
4820 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
4821 // transaction procceds without an authorization header.
4822 MockWrite data_writes2[] = {
4823 MockWrite("GET / HTTP/1.1\r\n"
4824 "Host: www.example.org\r\n"
4825 "Connection: keep-alive\r\n\r\n"),
4826 };
4827
4828 MockRead data_reads2[] = {
4829 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4830 "WWW-Authenticate: Mock\r\n"
4831 "Connection: keep-alive\r\n\r\n"),
4832 };
4833
4834 MockWrite data_writes3[] = {
4835 MockWrite("GET / HTTP/1.1\r\n"
4836 "Host: www.example.org\r\n"
4837 "Connection: keep-alive\r\n"
4838 "Authorization: auth_token\r\n\r\n"),
4839 };
4840
4841 MockRead data_reads3[] = {
4842 MockRead("HTTP/1.1 200 OK\r\n"
4843 "Content-Length: 5\r\n"
4844 "Content-Type: text/plain\r\n"
4845 "Connection: keep-alive\r\n\r\n"
4846 "Hello"),
4847 };
4848
Ryan Sleevib8d7ea02018-05-07 20:01:014849 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:164850 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4851
Ryan Sleevib8d7ea02018-05-07 20:01:014852 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:164853 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4854
Ryan Sleevib8d7ea02018-05-07 20:01:014855 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:164856 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4857
bnc87dcefc2017-05-25 12:47:584858 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194859 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:164860
4861 TestCompletionCallback callback;
4862 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4863 EXPECT_THAT(callback.GetResult(rv), IsOk());
4864
4865 const HttpResponseInfo* response = trans->GetResponseInfo();
4866 ASSERT_TRUE(response);
4867 ASSERT_TRUE(response->headers);
4868 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4869
4870 // The following three tests assert that an authentication challenge was
4871 // received and that the stack is ready to respond to the challenge using
4872 // ambient credentials.
4873 EXPECT_EQ(401, response->headers->response_code());
4874 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584875 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164876
4877 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4878 EXPECT_THAT(callback.GetResult(rv), IsOk());
4879 response = trans->GetResponseInfo();
4880 ASSERT_TRUE(response);
4881 ASSERT_TRUE(response->headers);
4882
4883 // The following three tests assert that an authentication challenge was
4884 // received and that the stack needs explicit credentials before it is ready
4885 // to respond to the challenge.
4886 EXPECT_EQ(401, response->headers->response_code());
4887 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584888 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164889
4890 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4891 EXPECT_THAT(callback.GetResult(rv), IsOk());
4892 response = trans->GetResponseInfo();
4893 ASSERT_TRUE(response);
4894 ASSERT_TRUE(response->headers);
4895 EXPECT_EQ(200, response->headers->response_code());
4896
4897 trans.reset();
4898 session->CloseAllConnections();
4899}
4900
Matt Menked1eb6d42018-01-17 04:54:064901// Proxy resolver that returns a proxy with the same host and port for different
4902// schemes, based on the path of the URL being requests.
4903class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
4904 public:
4905 SameProxyWithDifferentSchemesProxyResolver() {}
4906 ~SameProxyWithDifferentSchemesProxyResolver() override {}
4907
4908 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
4909
4910 static HostPortPair ProxyHostPortPair() {
4911 return HostPortPair::FromString(ProxyHostPortPairAsString());
4912 }
4913
4914 // ProxyResolver implementation.
4915 int GetProxyForURL(const GURL& url,
4916 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:174917 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:064918 std::unique_ptr<Request>* request,
4919 const NetLogWithSource& /*net_log*/) override {
4920 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:574921 results->set_traffic_annotation(
4922 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:064923 if (url.path() == "/socks4") {
4924 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
4925 return OK;
4926 }
4927 if (url.path() == "/socks5") {
4928 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
4929 return OK;
4930 }
4931 if (url.path() == "/http") {
4932 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
4933 return OK;
4934 }
4935 if (url.path() == "/https") {
4936 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
4937 return OK;
4938 }
Matt Menkee8648fa2019-01-17 16:47:074939 if (url.path() == "/https_trusted") {
4940 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
4941 ProxyHostPortPair(),
4942 true /* is_trusted_proxy */));
4943 return OK;
4944 }
Matt Menked1eb6d42018-01-17 04:54:064945 NOTREACHED();
4946 return ERR_NOT_IMPLEMENTED;
4947 }
4948
4949 private:
4950 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
4951};
4952
4953class SameProxyWithDifferentSchemesProxyResolverFactory
4954 : public ProxyResolverFactory {
4955 public:
4956 SameProxyWithDifferentSchemesProxyResolverFactory()
4957 : ProxyResolverFactory(false) {}
4958
Lily Houghton99597862018-03-07 16:40:424959 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
4960 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:174961 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:424962 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:064963 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
4964 return OK;
4965 }
4966
4967 private:
4968 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
4969};
4970
4971// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:074972// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:064973// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
4974// request to foo.com using proxy.com as an HTTP proxy.
4975TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:494976 session_deps_.proxy_resolution_service =
4977 std::make_unique<ProxyResolutionService>(
4978 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
4979 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
4980 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
4981 nullptr);
Matt Menked1eb6d42018-01-17 04:54:064982
4983 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4984
4985 MockWrite socks_writes[] = {
4986 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
4987 kSOCKS4OkRequestLocalHostPort80Length),
4988 MockWrite(SYNCHRONOUS,
4989 "GET /socks4 HTTP/1.1\r\n"
4990 "Host: test\r\n"
4991 "Connection: keep-alive\r\n\r\n"),
4992 };
4993 MockRead socks_reads[] = {
4994 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
4995 MockRead("HTTP/1.0 200 OK\r\n"
4996 "Connection: keep-alive\r\n"
4997 "Content-Length: 15\r\n\r\n"
4998 "SOCKS4 Response"),
4999 };
Ryan Sleevib8d7ea02018-05-07 20:01:015000 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065001 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5002
5003 const char kSOCKS5Request[] = {
5004 0x05, // Version
5005 0x01, // Command (CONNECT)
5006 0x00, // Reserved
5007 0x03, // Address type (DOMAINNAME)
5008 0x04, // Length of domain (4)
5009 't', 'e', 's', 't', // Domain string
5010 0x00, 0x50, // 16-bit port (80)
5011 };
5012 MockWrite socks5_writes[] = {
5013 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245014 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065015 MockWrite(SYNCHRONOUS,
5016 "GET /socks5 HTTP/1.1\r\n"
5017 "Host: test\r\n"
5018 "Connection: keep-alive\r\n\r\n"),
5019 };
5020 MockRead socks5_reads[] = {
5021 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5022 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5023 MockRead("HTTP/1.0 200 OK\r\n"
5024 "Connection: keep-alive\r\n"
5025 "Content-Length: 15\r\n\r\n"
5026 "SOCKS5 Response"),
5027 };
Ryan Sleevib8d7ea02018-05-07 20:01:015028 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065029 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5030
5031 MockWrite http_writes[] = {
5032 MockWrite(SYNCHRONOUS,
5033 "GET http://test/http HTTP/1.1\r\n"
5034 "Host: test\r\n"
5035 "Proxy-Connection: keep-alive\r\n\r\n"),
5036 };
5037 MockRead http_reads[] = {
5038 MockRead("HTTP/1.1 200 OK\r\n"
5039 "Proxy-Connection: keep-alive\r\n"
5040 "Content-Length: 13\r\n\r\n"
5041 "HTTP Response"),
5042 };
Ryan Sleevib8d7ea02018-05-07 20:01:015043 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065044 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5045
5046 MockWrite https_writes[] = {
5047 MockWrite(SYNCHRONOUS,
5048 "GET http://test/https HTTP/1.1\r\n"
5049 "Host: test\r\n"
5050 "Proxy-Connection: keep-alive\r\n\r\n"),
5051 };
5052 MockRead https_reads[] = {
5053 MockRead("HTTP/1.1 200 OK\r\n"
5054 "Proxy-Connection: keep-alive\r\n"
5055 "Content-Length: 14\r\n\r\n"
5056 "HTTPS Response"),
5057 };
Ryan Sleevib8d7ea02018-05-07 20:01:015058 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065059 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5060 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5061 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5062
Matt Menkee8648fa2019-01-17 16:47:075063 MockWrite https_trusted_writes[] = {
5064 MockWrite(SYNCHRONOUS,
5065 "GET http://test/https_trusted HTTP/1.1\r\n"
5066 "Host: test\r\n"
5067 "Proxy-Connection: keep-alive\r\n\r\n"),
5068 };
5069 MockRead https_trusted_reads[] = {
5070 MockRead("HTTP/1.1 200 OK\r\n"
5071 "Proxy-Connection: keep-alive\r\n"
5072 "Content-Length: 22\r\n\r\n"
5073 "HTTPS Trusted Response"),
5074 };
5075 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5076 https_trusted_writes);
5077 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5078 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5079 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5080
Matt Menked1eb6d42018-01-17 04:54:065081 struct TestCase {
5082 GURL url;
5083 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075084 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065085 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075086 int expected_idle_socks4_sockets;
5087 int expected_idle_socks5_sockets;
5088 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5089 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065090 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075091 int expected_idle_https_sockets;
5092 // How many idle sockets there should be in the HTTPS proxy socket pool with
5093 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5094 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065095 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075096 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5097 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5098 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5099 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5100 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5101 1},
Matt Menked1eb6d42018-01-17 04:54:065102 };
5103
5104 for (const auto& test_case : kTestCases) {
5105 HttpRequestInfo request;
5106 request.method = "GET";
5107 request.url = test_case.url;
Ramin Halavatib5e433e2018-02-07 07:41:105108 request.traffic_annotation =
5109 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065110 std::unique_ptr<HttpNetworkTransaction> trans =
5111 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5112 session.get());
5113 TestCompletionCallback callback;
5114 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5115 EXPECT_THAT(callback.GetResult(rv), IsOk());
5116
5117 const HttpResponseInfo* response = trans->GetResponseInfo();
5118 ASSERT_TRUE(response);
5119 ASSERT_TRUE(response->headers);
5120 EXPECT_EQ(200, response->headers->response_code());
5121 std::string response_data;
5122 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5123 EXPECT_EQ(test_case.expected_response, response_data);
5124
5125 // Return the socket to the socket pool, so can make sure it's not used for
5126 // the next requests.
5127 trans.reset();
5128 base::RunLoop().RunUntilIdle();
5129
5130 // Check the number of idle sockets in the pool, to make sure that used
5131 // sockets are indeed being returned to the socket pool. If each request
5132 // doesn't return an idle socket to the pool, the test would incorrectly
5133 // pass.
Matt Menkee8648fa2019-01-17 16:47:075134 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5135 session
Matt Menked23ab952019-03-06 00:24:405136 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075137 HttpNetworkSession::NORMAL_SOCKET_POOL,
5138 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5139 SameProxyWithDifferentSchemesProxyResolver::
5140 ProxyHostPortPair()))
5141 ->IdleSocketCount());
5142 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5143 session
Matt Menked23ab952019-03-06 00:24:405144 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075145 HttpNetworkSession::NORMAL_SOCKET_POOL,
5146 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5147 SameProxyWithDifferentSchemesProxyResolver::
5148 ProxyHostPortPair()))
5149 ->IdleSocketCount());
5150 EXPECT_EQ(test_case.expected_idle_http_sockets,
5151 session
Matt Menked23ab952019-03-06 00:24:405152 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075153 HttpNetworkSession::NORMAL_SOCKET_POOL,
5154 ProxyServer(ProxyServer::SCHEME_HTTP,
5155 SameProxyWithDifferentSchemesProxyResolver::
5156 ProxyHostPortPair()))
5157 ->IdleSocketCount());
5158 EXPECT_EQ(test_case.expected_idle_https_sockets,
5159 session
Matt Menked23ab952019-03-06 00:24:405160 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075161 HttpNetworkSession::NORMAL_SOCKET_POOL,
5162 ProxyServer(ProxyServer::SCHEME_HTTPS,
5163 SameProxyWithDifferentSchemesProxyResolver::
5164 ProxyHostPortPair()))
5165 ->IdleSocketCount());
5166 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5167 session
Matt Menked23ab952019-03-06 00:24:405168 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075169 HttpNetworkSession::NORMAL_SOCKET_POOL,
5170 ProxyServer(ProxyServer::SCHEME_HTTPS,
5171 SameProxyWithDifferentSchemesProxyResolver::
5172 ProxyHostPortPair(),
5173 true /* is_trusted_proxy */))
5174 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065175 }
5176}
5177
[email protected]029c83b62013-01-24 05:28:205178// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015179TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205180 HttpRequestInfo request1;
5181 request1.method = "GET";
bncce36dca22015-04-21 22:11:235182 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105183 request1.traffic_annotation =
5184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205185
5186 HttpRequestInfo request2;
5187 request2.method = "GET";
bncce36dca22015-04-21 22:11:235188 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105189 request2.traffic_annotation =
5190 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205191
5192 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495193 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5194 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515195 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075196 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095197 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205198
5199 // Since we have proxy, should try to establish tunnel.
5200 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175201 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5202 "Host: www.example.org:443\r\n"
5203 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205204
rsleevidb16bb02015-11-12 23:47:175205 MockWrite("GET /1 HTTP/1.1\r\n"
5206 "Host: www.example.org\r\n"
5207 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205208
rsleevidb16bb02015-11-12 23:47:175209 MockWrite("GET /2 HTTP/1.1\r\n"
5210 "Host: www.example.org\r\n"
5211 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205212 };
5213
5214 // The proxy responds to the connect with a 407, using a persistent
5215 // connection.
5216 MockRead data_reads1[] = {
5217 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5218
5219 MockRead("HTTP/1.1 200 OK\r\n"),
5220 MockRead("Content-Length: 1\r\n\r\n"),
5221 MockRead(SYNCHRONOUS, "1"),
5222
5223 MockRead("HTTP/1.1 200 OK\r\n"),
5224 MockRead("Content-Length: 2\r\n\r\n"),
5225 MockRead(SYNCHRONOUS, "22"),
5226 };
5227
Ryan Sleevib8d7ea02018-05-07 20:01:015228 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075229 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205230 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075231 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205232
5233 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585234 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195235 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205236
5237 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015238 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205239
5240 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015241 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205242
5243 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525244 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475245 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525246 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205247 EXPECT_EQ(1, response1->headers->GetContentLength());
5248
5249 LoadTimingInfo load_timing_info1;
5250 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5251 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5252
5253 trans1.reset();
5254
5255 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585256 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195257 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205258
5259 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015260 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205261
5262 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015263 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205264
5265 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525266 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475267 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525268 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205269 EXPECT_EQ(2, response2->headers->GetContentLength());
5270
5271 LoadTimingInfo load_timing_info2;
5272 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5273 TestLoadTimingReused(load_timing_info2);
5274
5275 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5276
5277 trans2.reset();
5278 session->CloseAllConnections();
5279}
5280
5281// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015282TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205283 HttpRequestInfo request1;
5284 request1.method = "GET";
bncce36dca22015-04-21 22:11:235285 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e2018-02-07 07:41:105286 request1.traffic_annotation =
5287 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205288
5289 HttpRequestInfo request2;
5290 request2.method = "GET";
bncce36dca22015-04-21 22:11:235291 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e2018-02-07 07:41:105292 request2.traffic_annotation =
5293 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205294
5295 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595296 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495297 ProxyResolutionService::CreateFixedFromPacResult(
5298 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515299 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075300 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095301 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205302
5303 // Since we have proxy, should try to establish tunnel.
5304 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175305 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5306 "Host: www.example.org:443\r\n"
5307 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205308
rsleevidb16bb02015-11-12 23:47:175309 MockWrite("GET /1 HTTP/1.1\r\n"
5310 "Host: www.example.org\r\n"
5311 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205312
rsleevidb16bb02015-11-12 23:47:175313 MockWrite("GET /2 HTTP/1.1\r\n"
5314 "Host: www.example.org\r\n"
5315 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205316 };
5317
5318 // The proxy responds to the connect with a 407, using a persistent
5319 // connection.
5320 MockRead data_reads1[] = {
5321 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5322
5323 MockRead("HTTP/1.1 200 OK\r\n"),
5324 MockRead("Content-Length: 1\r\n\r\n"),
5325 MockRead(SYNCHRONOUS, "1"),
5326
5327 MockRead("HTTP/1.1 200 OK\r\n"),
5328 MockRead("Content-Length: 2\r\n\r\n"),
5329 MockRead(SYNCHRONOUS, "22"),
5330 };
5331
Ryan Sleevib8d7ea02018-05-07 20:01:015332 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075333 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205334 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205336
5337 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585338 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195339 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205340
5341 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015342 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205343
5344 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015345 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205346
5347 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525348 ASSERT_TRUE(response1);
5349 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205350 EXPECT_EQ(1, response1->headers->GetContentLength());
5351
5352 LoadTimingInfo load_timing_info1;
5353 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5354 TestLoadTimingNotReusedWithPac(load_timing_info1,
5355 CONNECT_TIMING_HAS_SSL_TIMES);
5356
5357 trans1.reset();
5358
5359 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585360 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195361 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205362
5363 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015364 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205365
5366 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015367 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205368
5369 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525370 ASSERT_TRUE(response2);
5371 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205372 EXPECT_EQ(2, response2->headers->GetContentLength());
5373
5374 LoadTimingInfo load_timing_info2;
5375 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5376 TestLoadTimingReusedWithPac(load_timing_info2);
5377
5378 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5379
5380 trans2.reset();
5381 session->CloseAllConnections();
5382}
5383
[email protected]2df19bb2010-08-25 20:13:465384// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015385TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275386 HttpRequestInfo request;
5387 request.method = "GET";
bncce36dca22015-04-21 22:11:235388 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105389 request.traffic_annotation =
5390 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275391
[email protected]2df19bb2010-08-25 20:13:465392 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495393 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5394 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515395 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075396 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095397 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:465398
[email protected]2df19bb2010-08-25 20:13:465399 // Since we have proxy, should use full url
5400 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235401 MockWrite(
5402 "GET http://www.example.org/ HTTP/1.1\r\n"
5403 "Host: www.example.org\r\n"
5404 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465405 };
5406
5407 MockRead data_reads1[] = {
5408 MockRead("HTTP/1.1 200 OK\r\n"),
5409 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5410 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065411 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465412 };
5413
Ryan Sleevib8d7ea02018-05-07 20:01:015414 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075415 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065416 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075417 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465418
[email protected]49639fa2011-12-20 23:22:415419 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465420
bnc691fda62016-08-12 00:43:165421 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505422
bnc691fda62016-08-12 00:43:165423 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015424 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465425
5426 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015427 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465428
[email protected]58e32bb2013-01-21 18:23:255429 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165430 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255431 TestLoadTimingNotReused(load_timing_info,
5432 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5433
bnc691fda62016-08-12 00:43:165434 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525435 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465436
tbansal2ecbbc72016-10-06 17:15:475437 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:465438 EXPECT_TRUE(response->headers->IsKeepAlive());
5439 EXPECT_EQ(200, response->headers->response_code());
5440 EXPECT_EQ(100, response->headers->GetContentLength());
5441 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5442
5443 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585444 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:465445}
5446
[email protected]7642b5ae2010-09-01 20:55:175447// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015448TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275449 HttpRequestInfo request;
5450 request.method = "GET";
bncce36dca22015-04-21 22:11:235451 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105452 request.traffic_annotation =
5453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275454
[email protected]7642b5ae2010-09-01 20:55:175455 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495456 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5457 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515458 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075459 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095460 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:175461
bncce36dca22015-04-21 22:11:235462 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135463 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455464 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415465 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:175466
Ryan Hamilton0239aac2018-05-19 00:03:135467 spdy::SpdySerializedFrame resp(
5468 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5469 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:175470 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415471 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:175472 };
5473
Ryan Sleevib8d7ea02018-05-07 20:01:015474 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075475 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:175476
[email protected]8ddf8322012-02-23 18:08:065477 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365478 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075479 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:175480
[email protected]49639fa2011-12-20 23:22:415481 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:175482
bnc691fda62016-08-12 00:43:165483 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505484
bnc691fda62016-08-12 00:43:165485 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015486 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:175487
5488 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015489 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:175490
[email protected]58e32bb2013-01-21 18:23:255491 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165492 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255493 TestLoadTimingNotReused(load_timing_info,
5494 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5495
bnc691fda62016-08-12 00:43:165496 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525497 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:475498 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:525499 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025500 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:175501
5502 std::string response_data;
bnc691fda62016-08-12 00:43:165503 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235504 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:175505}
5506
[email protected]1c173852014-06-19 12:51:505507// Verifies that a session which races and wins against the owning transaction
5508// (completing prior to host resolution), doesn't fail the transaction.
5509// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:015510TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:505511 HttpRequestInfo request;
5512 request.method = "GET";
bncce36dca22015-04-21 22:11:235513 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105514 request.traffic_annotation =
5515 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:505516
5517 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495518 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5519 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515520 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:505521 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095522 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:505523
bncce36dca22015-04-21 22:11:235524 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:135525 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455526 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415527 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:505528
Raul Tambre94493c652019-03-11 17:18:355529 spdy::SpdySerializedFrame resp(
5530 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135531 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:505532 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415533 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:505534 };
5535
Ryan Sleevib8d7ea02018-05-07 20:01:015536 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:505537 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5538
5539 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365540 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:505541 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5542
5543 TestCompletionCallback callback1;
5544
bnc691fda62016-08-12 00:43:165545 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:505546
5547 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:505548 session_deps_.host_resolver->set_ondemand_mode(true);
5549
bnc691fda62016-08-12 00:43:165550 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015551 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:505552
5553 // Race a session to the proxy, which completes first.
5554 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:045555 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115556 PRIVACY_MODE_DISABLED,
5557 SpdySessionKey::IsProxySession::kTrue, SocketTag());
[email protected]1c173852014-06-19 12:51:505558 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:525559 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:505560
5561 // Unstall the resolution begun by the transaction.
5562 session_deps_.host_resolver->set_ondemand_mode(true);
5563 session_deps_.host_resolver->ResolveAllPending();
5564
5565 EXPECT_FALSE(callback1.have_result());
5566 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015567 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:505568
bnc691fda62016-08-12 00:43:165569 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525570 ASSERT_TRUE(response);
5571 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025572 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:505573
5574 std::string response_data;
bnc691fda62016-08-12 00:43:165575 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:505576 EXPECT_EQ(kUploadData, response_data);
5577}
5578
[email protected]dc7bd1c52010-11-12 00:01:135579// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015580TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:275581 HttpRequestInfo request;
5582 request.method = "GET";
bncce36dca22015-04-21 22:11:235583 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105584 request.traffic_annotation =
5585 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275586
[email protected]79cb5c12011-09-12 13:12:045587 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495588 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5589 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515590 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075591 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095592 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:135593
[email protected]dc7bd1c52010-11-12 00:01:135594 // The first request will be a bare GET, the second request will be a
5595 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:455596 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:135597 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485598 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385599 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:135600 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465601 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:135602 };
Ryan Hamilton0239aac2018-05-19 00:03:135603 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245604 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485605 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:135606 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415607 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:135608 };
5609
5610 // The first response is a 407 proxy authentication challenge, and the second
5611 // response will be a 200 response since the second request includes a valid
5612 // Authorization header.
5613 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465614 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:135615 };
Ryan Hamilton0239aac2018-05-19 00:03:135616 spdy::SpdySerializedFrame resp_authentication(
5617 spdy_util_.ConstructSpdyReplyError(
5618 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245619 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135620 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415621 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135622 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:355623 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135624 spdy::SpdySerializedFrame body_data(
5625 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:135626 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415627 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465628 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415629 CreateMockRead(resp_data, 4),
5630 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:135631 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:135632 };
5633
Ryan Sleevib8d7ea02018-05-07 20:01:015634 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075635 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:135636
[email protected]8ddf8322012-02-23 18:08:065637 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365638 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075639 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:135640
[email protected]49639fa2011-12-20 23:22:415641 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:135642
bnc691fda62016-08-12 00:43:165643 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:135644
bnc691fda62016-08-12 00:43:165645 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015646 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135647
5648 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015649 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135650
bnc691fda62016-08-12 00:43:165651 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135652
wezca1070932016-05-26 20:30:525653 ASSERT_TRUE(response);
5654 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:135655 EXPECT_EQ(407, response->headers->response_code());
5656 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585657 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:135658
[email protected]49639fa2011-12-20 23:22:415659 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:135660
bnc691fda62016-08-12 00:43:165661 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015662 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135663
5664 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015665 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135666
bnc691fda62016-08-12 00:43:165667 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135668
wezca1070932016-05-26 20:30:525669 ASSERT_TRUE(response_restart);
5670 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:135671 EXPECT_EQ(200, response_restart->headers->response_code());
5672 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585673 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:135674}
5675
[email protected]d9da5fe2010-10-13 22:37:165676// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:015677TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:275678 HttpRequestInfo request;
5679 request.method = "GET";
bncce36dca22015-04-21 22:11:235680 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105681 request.traffic_annotation =
5682 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275683
[email protected]d9da5fe2010-10-13 22:37:165684 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495685 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5686 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515687 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075688 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095689 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165690
bnc691fda62016-08-12 00:43:165691 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165692
bncce36dca22015-04-21 22:11:235693 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135694 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045695 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5696 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235697 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:165698
bncce36dca22015-04-21 22:11:235699 const char get[] =
5700 "GET / HTTP/1.1\r\n"
5701 "Host: www.example.org\r\n"
5702 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135703 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:195704 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:135705 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355706 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:165707 const char resp[] = "HTTP/1.1 200 OK\r\n"
5708 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135709 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:195710 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:135711 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:195712 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:135713 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:415714 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:045715
5716 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415717 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5718 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:045719 };
5720
[email protected]d9da5fe2010-10-13 22:37:165721 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415722 CreateMockRead(conn_resp, 1, ASYNC),
5723 CreateMockRead(wrapped_get_resp, 3, ASYNC),
5724 CreateMockRead(wrapped_body, 4, ASYNC),
5725 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135726 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:165727 };
5728
Ryan Sleevib8d7ea02018-05-07 20:01:015729 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075730 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165731
[email protected]8ddf8322012-02-23 18:08:065732 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365733 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075734 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065735 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075736 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165737
[email protected]49639fa2011-12-20 23:22:415738 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165739
bnc691fda62016-08-12 00:43:165740 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015741 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165742
5743 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015744 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165745
[email protected]58e32bb2013-01-21 18:23:255746 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165747 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255748 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5749
bnc691fda62016-08-12 00:43:165750 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525751 ASSERT_TRUE(response);
5752 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:165753 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5754
5755 std::string response_data;
bnc691fda62016-08-12 00:43:165756 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:165757 EXPECT_EQ("1234567890", response_data);
5758}
5759
5760// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:015761TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
5762 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:385763
[email protected]cb9bf6ca2011-01-28 13:15:275764 HttpRequestInfo request;
5765 request.method = "GET";
bncce36dca22015-04-21 22:11:235766 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105767 request.traffic_annotation =
5768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275769
[email protected]d9da5fe2010-10-13 22:37:165770 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495771 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5772 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515773 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075774 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095775 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165776
bnc691fda62016-08-12 00:43:165777 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165778
bncce36dca22015-04-21 22:11:235779 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135780 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045781 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5782 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235783 // fetch https://www.example.org/ via SPDY
5784 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:135785 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:495786 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135787 spdy::SpdySerializedFrame wrapped_get(
5788 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
5789 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355790 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135791 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355792 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135793 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:025794 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135795 spdy::SpdySerializedFrame body(
5796 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
5797 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:025798 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135799 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:415800 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:135801 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:415802 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:045803
5804 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415805 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5806 CreateMockWrite(window_update_get_resp, 6),
5807 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:045808 };
5809
[email protected]d9da5fe2010-10-13 22:37:165810 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415811 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:095812 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:415813 CreateMockRead(wrapped_get_resp, 4, ASYNC),
5814 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135815 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:165816 };
5817
Ryan Sleevib8d7ea02018-05-07 20:01:015818 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075819 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165820
[email protected]8ddf8322012-02-23 18:08:065821 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365822 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075823 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065824 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365825 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075826 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165827
[email protected]49639fa2011-12-20 23:22:415828 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165829
bnc691fda62016-08-12 00:43:165830 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015831 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165832
rch32320842015-05-16 15:57:095833 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:555834 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:095835 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:595836 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:165837 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015838 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165839
[email protected]58e32bb2013-01-21 18:23:255840 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165841 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255842 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5843
bnc691fda62016-08-12 00:43:165844 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525845 ASSERT_TRUE(response);
5846 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025847 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:165848
5849 std::string response_data;
bnc691fda62016-08-12 00:43:165850 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235851 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:165852}
5853
5854// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015855TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:275856 HttpRequestInfo request;
5857 request.method = "GET";
bncce36dca22015-04-21 22:11:235858 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:105859 request.traffic_annotation =
5860 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275861
[email protected]d9da5fe2010-10-13 22:37:165862 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495863 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5864 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515865 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075866 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095867 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165868
bnc691fda62016-08-12 00:43:165869 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165870
bncce36dca22015-04-21 22:11:235871 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135872 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045873 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5874 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:135875 spdy::SpdySerializedFrame get(
5876 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:165877
5878 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415879 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:165880 };
5881
Ryan Hamilton0239aac2018-05-19 00:03:135882 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
5883 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:165884 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415885 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:165886 };
5887
Ryan Sleevib8d7ea02018-05-07 20:01:015888 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075889 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165890
[email protected]8ddf8322012-02-23 18:08:065891 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365892 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075893 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065894 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365895 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075896 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165897
[email protected]49639fa2011-12-20 23:22:415898 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165899
bnc691fda62016-08-12 00:43:165900 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015901 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165902
5903 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015904 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:165905
ttuttle960fcbf2016-04-19 13:26:325906 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:165907}
5908
Matt Menkecb2cd0982018-12-19 17:54:045909// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:245910// is observed, but does exist by the time auth credentials are provided. In
5911// this case, auth and SSL are fully negotated on the second request, but then
5912// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:045913TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
5914 ProxyConfig proxy_config;
5915 proxy_config.set_auto_detect(true);
5916 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
5917
5918 CapturingProxyResolver capturing_proxy_resolver;
5919 capturing_proxy_resolver.set_proxy_server(
5920 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
5921 session_deps_.proxy_resolution_service =
5922 std::make_unique<ProxyResolutionService>(
5923 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5924 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
5925 std::make_unique<CapturingProxyResolverFactory>(
5926 &capturing_proxy_resolver),
5927 nullptr);
5928
5929 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5930
5931 const char kMyUrl[] = "https://www.example.org/";
5932 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
5933 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355934 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:045935 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5936
5937 spdy_util_.UpdateWithStreamDestruction(1);
5938 spdy::SpdySerializedFrame get2(
5939 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
5940 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:355941 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:045942 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
5943
5944 MockWrite auth_challenge_writes[] = {
5945 MockWrite(ASYNC, 0,
5946 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5947 "Host: www.example.org:443\r\n"
5948 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:245949 MockWrite(ASYNC, 2,
5950 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5951 "Host: www.example.org:443\r\n"
5952 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menkecb2cd0982018-12-19 17:54:045953 };
5954
5955 MockRead auth_challenge_reads[] = {
5956 MockRead(ASYNC, 1,
5957 "HTTP/1.1 407 Authentication Required\r\n"
5958 "Content-Length: 0\r\n"
5959 "Proxy-Connection: close\r\n"
5960 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
5961 };
5962
5963 MockWrite spdy_writes[] = {
5964 MockWrite(ASYNC, 0,
5965 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5966 "Host: www.example.org:443\r\n"
5967 "Proxy-Connection: keep-alive\r\n"
5968 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5969 CreateMockWrite(get, 2),
5970 CreateMockWrite(get2, 5),
5971 };
5972
5973 MockRead spdy_reads[] = {
5974 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5975 CreateMockRead(get_resp, 3, ASYNC),
5976 CreateMockRead(body, 4, ASYNC),
5977 CreateMockRead(get_resp2, 6, ASYNC),
5978 CreateMockRead(body2, 7, ASYNC),
5979
5980 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
5981 };
5982
Matt Menke5062be22019-05-01 17:50:245983 MockWrite auth_response_writes_discarded_socket[] = {
5984 MockWrite(ASYNC, 0,
5985 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5986 "Host: www.example.org:443\r\n"
5987 "Proxy-Connection: keep-alive\r\n"
5988 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5989 };
5990
5991 MockRead auth_response_reads_discarded_socket[] = {
5992 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5993 };
5994
Matt Menkecb2cd0982018-12-19 17:54:045995 SequencedSocketData auth_challenge1(auth_challenge_reads,
5996 auth_challenge_writes);
5997 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
5998
5999 SequencedSocketData auth_challenge2(auth_challenge_reads,
6000 auth_challenge_writes);
6001 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
6002
6003 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6004 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6005
Matt Menke5062be22019-05-01 17:50:246006 SequencedSocketData auth_response_discarded_socket(
6007 auth_response_reads_discarded_socket,
6008 auth_response_writes_discarded_socket);
6009 session_deps_.socket_factory->AddSocketDataProvider(
6010 &auth_response_discarded_socket);
6011
Matt Menkecb2cd0982018-12-19 17:54:046012 SSLSocketDataProvider ssl(ASYNC, OK);
6013 ssl.next_proto = kProtoHTTP2;
6014 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6015
Matt Menke5062be22019-05-01 17:50:246016 SSLSocketDataProvider ssl2(ASYNC, OK);
6017 ssl2.next_proto = kProtoHTTP2;
6018 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6019
Matt Menkecb2cd0982018-12-19 17:54:046020 TestCompletionCallback callback;
6021 std::string response_data;
6022
6023 // Run first request until an auth challenge is observed.
6024 HttpRequestInfo request1;
6025 request1.method = "GET";
6026 request1.url = GURL(kMyUrl);
6027 request1.traffic_annotation =
6028 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6029 HttpNetworkTransaction trans1(LOWEST, session.get());
6030 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6031 EXPECT_THAT(callback.GetResult(rv), IsOk());
6032 const HttpResponseInfo* response = trans1.GetResponseInfo();
6033 ASSERT_TRUE(response);
6034 ASSERT_TRUE(response->headers);
6035 EXPECT_EQ(407, response->headers->response_code());
6036 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586037 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046038
6039 // Run second request until an auth challenge is observed.
6040 HttpRequestInfo request2;
6041 request2.method = "GET";
6042 request2.url = GURL(kMyUrl);
6043 request2.traffic_annotation =
6044 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6045 HttpNetworkTransaction trans2(LOWEST, session.get());
6046 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6047 EXPECT_THAT(callback.GetResult(rv), IsOk());
6048 response = trans2.GetResponseInfo();
6049 ASSERT_TRUE(response);
6050 ASSERT_TRUE(response->headers);
6051 EXPECT_EQ(407, response->headers->response_code());
6052 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586053 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046054
6055 // Now provide credentials for the first request, and wait for it to complete.
6056 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6057 rv = callback.GetResult(rv);
6058 EXPECT_THAT(rv, IsOk());
6059 response = trans1.GetResponseInfo();
6060 ASSERT_TRUE(response);
6061 ASSERT_TRUE(response->headers);
6062 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6063 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6064 EXPECT_EQ(kUploadData, response_data);
6065
6066 // Now provide credentials for the second request. It should notice the
6067 // existing session, and reuse it.
6068 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6069 EXPECT_THAT(callback.GetResult(rv), IsOk());
6070 response = trans2.GetResponseInfo();
6071 ASSERT_TRUE(response);
6072 ASSERT_TRUE(response->headers);
6073 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6074 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6075 EXPECT_EQ(kUploadData, response_data);
6076}
6077
[email protected]f6c63db52013-02-02 00:35:226078// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6079// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016080TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226081 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6082 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496083 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6084 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516085 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076086 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096087 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506088 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226089
6090 HttpRequestInfo request1;
6091 request1.method = "GET";
bncce36dca22015-04-21 22:11:236092 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226093 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106094 request1.traffic_annotation =
6095 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226096
6097 HttpRequestInfo request2;
6098 request2.method = "GET";
bncce36dca22015-04-21 22:11:236099 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226100 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106101 request2.traffic_annotation =
6102 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226103
bncce36dca22015-04-21 22:11:236104 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136105 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046106 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6107 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136108 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356109 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226110
bncce36dca22015-04-21 22:11:236111 // Fetch https://www.example.org/ via HTTP.
6112 const char get1[] =
6113 "GET / HTTP/1.1\r\n"
6114 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226115 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136116 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196117 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226118 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6119 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136120 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196121 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136122 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196123 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136124 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416125 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226126
bncce36dca22015-04-21 22:11:236127 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136128 spdy::SpdyHeaderBlock connect2_block;
6129 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6130 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6131 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046132 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6133 false));
[email protected]601e03f12014-04-06 16:26:396134
Ryan Hamilton0239aac2018-05-19 00:03:136135 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356136 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226137
bncce36dca22015-04-21 22:11:236138 // Fetch https://mail.example.org/ via HTTP.
6139 const char get2[] =
6140 "GET / HTTP/1.1\r\n"
6141 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226142 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136143 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196144 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226145 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6146 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136147 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196148 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136149 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196150 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226151
6152 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416153 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6154 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226155 };
6156
6157 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416158 CreateMockRead(conn_resp1, 1, ASYNC),
6159 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6160 CreateMockRead(wrapped_body1, 4, ASYNC),
6161 CreateMockRead(conn_resp2, 6, ASYNC),
6162 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6163 CreateMockRead(wrapped_body2, 9, ASYNC),
6164 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226165 };
6166
Ryan Sleevib8d7ea02018-05-07 20:01:016167 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506168 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226169
6170 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366171 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506172 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226173 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506174 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226175 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506176 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226177
6178 TestCompletionCallback callback;
6179
bnc691fda62016-08-12 00:43:166180 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206181 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016182 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226183
6184 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166185 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226186 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6187
bnc691fda62016-08-12 00:43:166188 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526189 ASSERT_TRUE(response);
6190 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226191 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6192
6193 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446194 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166195 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506196 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226197
bnc691fda62016-08-12 00:43:166198 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206199 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016200 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226201
6202 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166203 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226204 // Even though the SPDY connection is reused, a new tunnelled connection has
6205 // to be created, so the socket's load timing looks like a fresh connection.
6206 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6207
6208 // The requests should have different IDs, since they each are using their own
6209 // separate stream.
6210 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6211
bnc691fda62016-08-12 00:43:166212 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506213 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226214}
6215
6216// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6217// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016218TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226219 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6220 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496221 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6222 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516223 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076224 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096225 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506226 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226227
6228 HttpRequestInfo request1;
6229 request1.method = "GET";
bncce36dca22015-04-21 22:11:236230 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226231 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106232 request1.traffic_annotation =
6233 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226234
6235 HttpRequestInfo request2;
6236 request2.method = "GET";
bncce36dca22015-04-21 22:11:236237 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226238 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106239 request2.traffic_annotation =
6240 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226241
bncce36dca22015-04-21 22:11:236242 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136243 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046244 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6245 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136246 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356247 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226248
bncce36dca22015-04-21 22:11:236249 // Fetch https://www.example.org/ via HTTP.
6250 const char get1[] =
6251 "GET / HTTP/1.1\r\n"
6252 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226253 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136254 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196255 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226256 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6257 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136258 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196259 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136260 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196261 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136262 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416263 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226264
bncce36dca22015-04-21 22:11:236265 // Fetch https://www.example.org/2 via HTTP.
6266 const char get2[] =
6267 "GET /2 HTTP/1.1\r\n"
6268 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226269 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136270 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196271 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226272 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6273 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136274 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196275 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136276 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196277 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226278
6279 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416280 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6281 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226282 };
6283
6284 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416285 CreateMockRead(conn_resp1, 1, ASYNC),
6286 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466287 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416288 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466289 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416290 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226291 };
6292
Ryan Sleevib8d7ea02018-05-07 20:01:016293 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506294 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226295
6296 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366297 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506298 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226299 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506300 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226301
6302 TestCompletionCallback callback;
6303
bnc87dcefc2017-05-25 12:47:586304 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196305 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206306 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016307 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226308
6309 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016310 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226311
6312 LoadTimingInfo load_timing_info;
6313 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6314 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6315
6316 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526317 ASSERT_TRUE(response);
6318 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226319 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6320
6321 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446322 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506323 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226324 trans.reset();
6325
bnc87dcefc2017-05-25 12:47:586326 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196327 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206328 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016329 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226330
[email protected]f6c63db52013-02-02 00:35:226331 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016332 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226333
6334 LoadTimingInfo load_timing_info2;
6335 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6336 TestLoadTimingReused(load_timing_info2);
6337
6338 // The requests should have the same ID.
6339 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6340
[email protected]90499482013-06-01 00:39:506341 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226342}
6343
6344// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6345// Proxy to different servers.
bncd16676a2016-07-20 16:23:016346TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226347 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496348 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6349 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516350 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076351 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096352 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506353 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226354
6355 HttpRequestInfo request1;
6356 request1.method = "GET";
bncce36dca22015-04-21 22:11:236357 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226358 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106359 request1.traffic_annotation =
6360 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226361
6362 HttpRequestInfo request2;
6363 request2.method = "GET";
bncce36dca22015-04-21 22:11:236364 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226365 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:106366 request2.traffic_annotation =
6367 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226368
bncce36dca22015-04-21 22:11:236369 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136370 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236371 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136372 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156373 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136374 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356375 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136376 spdy::SpdySerializedFrame body1(
6377 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386378 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226379
bncce36dca22015-04-21 22:11:236380 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136381 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236382 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136383 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156384 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136385 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356386 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136387 spdy::SpdySerializedFrame body2(
6388 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:226389
6390 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416391 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:226392 };
6393
6394 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416395 CreateMockRead(get_resp1, 1, ASYNC),
6396 CreateMockRead(body1, 2, ASYNC),
6397 CreateMockRead(get_resp2, 4, ASYNC),
6398 CreateMockRead(body2, 5, ASYNC),
6399 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:226400 };
6401
Ryan Sleevib8d7ea02018-05-07 20:01:016402 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506403 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226404
6405 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366406 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506407 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226408
6409 TestCompletionCallback callback;
6410
bnc87dcefc2017-05-25 12:47:586411 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196412 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206413 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016414 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226415
6416 LoadTimingInfo load_timing_info;
6417 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6418 TestLoadTimingNotReused(load_timing_info,
6419 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6420
6421 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526422 ASSERT_TRUE(response);
6423 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026424 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:226425
6426 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446427 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:506428 rv = trans->Read(buf.get(), 256, callback.callback());
6429 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226430 // Delete the first request, so the second one can reuse the socket.
6431 trans.reset();
6432
bnc691fda62016-08-12 00:43:166433 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206434 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016435 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226436
6437 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166438 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226439 TestLoadTimingReused(load_timing_info2);
6440
6441 // The requests should have the same ID.
6442 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6443
bnc691fda62016-08-12 00:43:166444 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506445 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226446}
6447
Matt Menke2436b2f2018-12-11 18:07:116448// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
6449// direct (non-proxied) request to the proxy server are not pooled, as that
6450// would break socket pool isolation.
6451TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
6452 ProxyConfig proxy_config;
6453 proxy_config.set_auto_detect(true);
6454 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6455
6456 CapturingProxyResolver capturing_proxy_resolver;
6457 session_deps_.proxy_resolution_service =
6458 std::make_unique<ProxyResolutionService>(
6459 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6460 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6461 std::make_unique<CapturingProxyResolverFactory>(
6462 &capturing_proxy_resolver),
6463 nullptr);
6464
6465 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6466
6467 SpdyTestUtil spdy_util1;
6468 // CONNECT to www.example.org:443 via HTTP/2.
6469 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046470 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6471 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116472 // fetch https://www.example.org/ via HTTP/2.
6473 const char kMyUrl[] = "https://www.example.org/";
6474 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6475 spdy::SpdySerializedFrame wrapped_get(
6476 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6477 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356478 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116479 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356480 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116481 spdy::SpdySerializedFrame wrapped_get_resp(
6482 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6483 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
6484 spdy::SpdySerializedFrame wrapped_body(
6485 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6486 spdy::SpdySerializedFrame window_update_get_resp(
6487 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6488 spdy::SpdySerializedFrame window_update_body(
6489 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6490
6491 MockWrite spdy_writes1[] = {
6492 CreateMockWrite(connect, 0),
6493 CreateMockWrite(wrapped_get, 2),
6494 CreateMockWrite(window_update_get_resp, 6),
6495 CreateMockWrite(window_update_body, 7),
6496 };
6497
6498 MockRead spdy_reads1[] = {
6499 CreateMockRead(conn_resp, 1, ASYNC),
6500 MockRead(ASYNC, ERR_IO_PENDING, 3),
6501 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6502 CreateMockRead(wrapped_body, 5, ASYNC),
6503 MockRead(ASYNC, 0, 8),
6504 };
6505
6506 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6507 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6508
6509 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
6510 // a new pipe.
6511 SpdyTestUtil spdy_util2;
6512 spdy::SpdySerializedFrame req(
6513 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6514 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
6515
6516 spdy::SpdySerializedFrame resp(
6517 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6518 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
6519 MockRead spdy_reads2[] = {
6520 CreateMockRead(resp, 1),
6521 CreateMockRead(data, 2),
6522 MockRead(ASYNC, 0, 3),
6523 };
6524 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6525 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6526
6527 SSLSocketDataProvider ssl(ASYNC, OK);
6528 ssl.next_proto = kProtoHTTP2;
6529 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6530 SSLSocketDataProvider ssl2(ASYNC, OK);
6531 ssl2.next_proto = kProtoHTTP2;
6532 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6533 SSLSocketDataProvider ssl3(ASYNC, OK);
6534 ssl3.next_proto = kProtoHTTP2;
6535 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6536
6537 TestCompletionCallback callback;
6538 std::string response_data;
6539
6540 // Make a request using proxy:70 as a HTTP/2 proxy.
6541 capturing_proxy_resolver.set_proxy_server(
6542 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6543 HttpRequestInfo request1;
6544 request1.method = "GET";
6545 request1.url = GURL("https://www.example.org/");
6546 request1.traffic_annotation =
6547 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6548
6549 HttpNetworkTransaction trans1(LOWEST, session.get());
6550 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6551 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6552
6553 // Allow the SpdyProxyClientSocket's write callback to complete.
6554 base::RunLoop().RunUntilIdle();
6555 // Now allow the read of the response to complete.
6556 spdy_data1.Resume();
6557 rv = callback.WaitForResult();
6558 EXPECT_THAT(rv, IsOk());
6559
6560 const HttpResponseInfo* response = trans1.GetResponseInfo();
6561 ASSERT_TRUE(response);
6562 ASSERT_TRUE(response->headers);
6563 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6564
6565 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6566 EXPECT_EQ(kUploadData, response_data);
6567 RunUntilIdle();
6568
6569 // Make a direct HTTP/2 request to proxy:70.
6570 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6571 HttpRequestInfo request2;
6572 request2.method = "GET";
6573 request2.url = GURL("https://proxy:70/");
6574 request2.traffic_annotation =
6575 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6576 HttpNetworkTransaction trans2(LOWEST, session.get());
6577 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
6578 NetLogWithSource())),
6579 IsOk());
6580 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6581}
6582
6583// Same as above, but reverse request order, since the code to check for an
6584// existing session is different for tunnels and direct connections.
6585TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
6586 // Configure against https proxy server "myproxy:80".
6587 ProxyConfig proxy_config;
6588 proxy_config.set_auto_detect(true);
6589 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6590
6591 CapturingProxyResolver capturing_proxy_resolver;
6592 session_deps_.proxy_resolution_service =
6593 std::make_unique<ProxyResolutionService>(
6594 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6595 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6596 std::make_unique<CapturingProxyResolverFactory>(
6597 &capturing_proxy_resolver),
6598 nullptr);
6599
6600 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6601 // Fetch https://proxy:70/ via HTTP/2.
6602 SpdyTestUtil spdy_util1;
6603 spdy::SpdySerializedFrame req(
6604 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6605 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
6606
6607 spdy::SpdySerializedFrame resp(
6608 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
6609 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
6610 MockRead spdy_reads1[] = {
6611 CreateMockRead(resp, 1),
6612 CreateMockRead(data, 2),
6613 MockRead(ASYNC, 0, 3),
6614 };
6615 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6616 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6617
6618 SpdyTestUtil spdy_util2;
6619 // CONNECT to www.example.org:443 via HTTP/2.
6620 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046621 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6622 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116623 // fetch https://www.example.org/ via HTTP/2.
6624 const char kMyUrl[] = "https://www.example.org/";
6625 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6626 spdy::SpdySerializedFrame wrapped_get(
6627 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6628 spdy::SpdySerializedFrame conn_resp(
6629 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6630 spdy::SpdySerializedFrame get_resp(
6631 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6632 spdy::SpdySerializedFrame wrapped_get_resp(
6633 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6634 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
6635 spdy::SpdySerializedFrame wrapped_body(
6636 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6637 spdy::SpdySerializedFrame window_update_get_resp(
6638 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6639 spdy::SpdySerializedFrame window_update_body(
6640 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6641
6642 MockWrite spdy_writes2[] = {
6643 CreateMockWrite(connect, 0),
6644 CreateMockWrite(wrapped_get, 2),
6645 CreateMockWrite(window_update_get_resp, 6),
6646 CreateMockWrite(window_update_body, 7),
6647 };
6648
6649 MockRead spdy_reads2[] = {
6650 CreateMockRead(conn_resp, 1, ASYNC),
6651 MockRead(ASYNC, ERR_IO_PENDING, 3),
6652 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6653 CreateMockRead(wrapped_body, 5, ASYNC),
6654 MockRead(ASYNC, 0, 8),
6655 };
6656
6657 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6658 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6659
6660 SSLSocketDataProvider ssl(ASYNC, OK);
6661 ssl.next_proto = kProtoHTTP2;
6662 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6663 SSLSocketDataProvider ssl2(ASYNC, OK);
6664 ssl2.next_proto = kProtoHTTP2;
6665 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6666 SSLSocketDataProvider ssl3(ASYNC, OK);
6667 ssl3.next_proto = kProtoHTTP2;
6668 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6669
6670 TestCompletionCallback callback;
6671 std::string response_data;
6672
6673 // Make a direct HTTP/2 request to proxy:70.
6674 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6675 HttpRequestInfo request1;
6676 request1.method = "GET";
6677 request1.url = GURL("https://proxy:70/");
6678 request1.traffic_annotation =
6679 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6680 HttpNetworkTransaction trans1(LOWEST, session.get());
6681 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
6682 NetLogWithSource())),
6683 IsOk());
6684 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6685 RunUntilIdle();
6686
6687 // Make a request using proxy:70 as a HTTP/2 proxy.
6688 capturing_proxy_resolver.set_proxy_server(
6689 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6690 HttpRequestInfo request2;
6691 request2.method = "GET";
6692 request2.url = GURL("https://www.example.org/");
6693 request2.traffic_annotation =
6694 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6695
6696 HttpNetworkTransaction trans2(LOWEST, session.get());
6697 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6698 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6699
6700 // Allow the SpdyProxyClientSocket's write callback to complete.
6701 base::RunLoop().RunUntilIdle();
6702 // Now allow the read of the response to complete.
6703 spdy_data2.Resume();
6704 rv = callback.WaitForResult();
6705 EXPECT_THAT(rv, IsOk());
6706
6707 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
6708 ASSERT_TRUE(response2);
6709 ASSERT_TRUE(response2->headers);
6710 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
6711
6712 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6713 EXPECT_EQ(kUploadData, response_data);
6714}
6715
[email protected]2df19bb2010-08-25 20:13:466716// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:016717TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:466718 HttpRequestInfo request;
6719 request.method = "GET";
bncce36dca22015-04-21 22:11:236720 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:466721 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:296722 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:106723 request.traffic_annotation =
6724 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:466725
[email protected]79cb5c12011-09-12 13:12:046726 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496727 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6728 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516729 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076730 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096731 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276732
[email protected]2df19bb2010-08-25 20:13:466733 // Since we have proxy, should use full url
6734 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:166735 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6736 "Host: www.example.org\r\n"
6737 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466738
bnc691fda62016-08-12 00:43:166739 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:236740 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:166741 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6742 "Host: www.example.org\r\n"
6743 "Proxy-Connection: keep-alive\r\n"
6744 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466745 };
6746
6747 // The proxy responds to the GET with a 407, using a persistent
6748 // connection.
6749 MockRead data_reads1[] = {
6750 // No credentials.
6751 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6752 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6753 MockRead("Proxy-Connection: keep-alive\r\n"),
6754 MockRead("Content-Length: 0\r\n\r\n"),
6755
6756 MockRead("HTTP/1.1 200 OK\r\n"),
6757 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6758 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066759 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466760 };
6761
Ryan Sleevib8d7ea02018-05-07 20:01:016762 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076763 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066764 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076765 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466766
[email protected]49639fa2011-12-20 23:22:416767 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466768
bnc691fda62016-08-12 00:43:166769 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506770
bnc691fda62016-08-12 00:43:166771 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016772 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466773
6774 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016775 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466776
[email protected]58e32bb2013-01-21 18:23:256777 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166778 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256779 TestLoadTimingNotReused(load_timing_info,
6780 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6781
bnc691fda62016-08-12 00:43:166782 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526783 ASSERT_TRUE(response);
6784 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:466785 EXPECT_EQ(407, response->headers->response_code());
6786 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586787 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:506788 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466789
[email protected]49639fa2011-12-20 23:22:416790 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:466791
bnc691fda62016-08-12 00:43:166792 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016793 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466794
6795 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016796 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466797
[email protected]58e32bb2013-01-21 18:23:256798 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:166799 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256800 // Retrying with HTTP AUTH is considered to be reusing a socket.
6801 TestLoadTimingReused(load_timing_info);
6802
bnc691fda62016-08-12 00:43:166803 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526804 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466805
6806 EXPECT_TRUE(response->headers->IsKeepAlive());
6807 EXPECT_EQ(200, response->headers->response_code());
6808 EXPECT_EQ(100, response->headers->GetContentLength());
6809 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:506810 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466811
6812 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586813 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466814}
6815
[email protected]23e482282013-06-14 16:08:026816void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:086817 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:426818 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:086819 request.method = "GET";
bncce36dca22015-04-21 22:11:236820 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:106821 request.traffic_annotation =
6822 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:086823
[email protected]cb9bf6ca2011-01-28 13:15:276824 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496825 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6826 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096827 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276828
[email protected]c744cf22009-02-27 07:28:086829 // Since we have proxy, should try to establish tunnel.
6830 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:176831 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6832 "Host: www.example.org:443\r\n"
6833 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:086834 };
6835
6836 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:236837 status, MockRead("Content-Length: 10\r\n\r\n"),
6838 // No response body because the test stops reading here.
6839 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:086840 };
6841
Ryan Sleevib8d7ea02018-05-07 20:01:016842 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:076843 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:086844
[email protected]49639fa2011-12-20 23:22:416845 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:086846
bnc691fda62016-08-12 00:43:166847 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506848
tfarina42834112016-09-22 13:38:206849 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016850 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:086851
6852 rv = callback.WaitForResult();
6853 EXPECT_EQ(expected_status, rv);
6854}
6855
[email protected]23e482282013-06-14 16:08:026856void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:236857 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:086858 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:426859 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:086860}
6861
bncd16676a2016-07-20 16:23:016862TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:086863 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
6864}
6865
bncd16676a2016-07-20 16:23:016866TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:086867 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
6868}
6869
bncd16676a2016-07-20 16:23:016870TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:086871 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
6872}
6873
bncd16676a2016-07-20 16:23:016874TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:086875 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
6876}
6877
bncd16676a2016-07-20 16:23:016878TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:086879 ConnectStatusHelper(
6880 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
6881}
6882
bncd16676a2016-07-20 16:23:016883TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:086884 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
6885}
6886
bncd16676a2016-07-20 16:23:016887TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:086888 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
6889}
6890
bncd16676a2016-07-20 16:23:016891TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:086892 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
6893}
6894
bncd16676a2016-07-20 16:23:016895TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:086896 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
6897}
6898
bncd16676a2016-07-20 16:23:016899TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:086900 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
6901}
6902
bncd16676a2016-07-20 16:23:016903TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:086904 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
6905}
6906
bncd16676a2016-07-20 16:23:016907TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:086908 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
6909}
6910
bncd16676a2016-07-20 16:23:016911TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:086912 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
6913}
6914
bncd16676a2016-07-20 16:23:016915TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:086916 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
6917}
6918
bncd16676a2016-07-20 16:23:016919TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:086920 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
6921}
6922
bncd16676a2016-07-20 16:23:016923TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:086924 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
6925}
6926
bncd16676a2016-07-20 16:23:016927TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:376928 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
6929}
6930
bncd16676a2016-07-20 16:23:016931TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:086932 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
6933}
6934
bncd16676a2016-07-20 16:23:016935TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:086936 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
6937}
6938
bncd16676a2016-07-20 16:23:016939TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:086940 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
6941}
6942
bncd16676a2016-07-20 16:23:016943TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:086944 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
6945}
6946
bncd16676a2016-07-20 16:23:016947TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:086948 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
6949}
6950
bncd16676a2016-07-20 16:23:016951TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:086952 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
6953}
6954
bncd16676a2016-07-20 16:23:016955TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:086956 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
6957}
6958
bncd16676a2016-07-20 16:23:016959TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:086960 ConnectStatusHelperWithExpectedStatus(
6961 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:546962 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:086963}
6964
bncd16676a2016-07-20 16:23:016965TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:086966 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
6967}
6968
bncd16676a2016-07-20 16:23:016969TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:086970 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
6971}
6972
bncd16676a2016-07-20 16:23:016973TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:086974 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
6975}
6976
bncd16676a2016-07-20 16:23:016977TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:086978 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
6979}
6980
bncd16676a2016-07-20 16:23:016981TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:086982 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
6983}
6984
bncd16676a2016-07-20 16:23:016985TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:086986 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
6987}
6988
bncd16676a2016-07-20 16:23:016989TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:086990 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
6991}
6992
bncd16676a2016-07-20 16:23:016993TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:086994 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
6995}
6996
bncd16676a2016-07-20 16:23:016997TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:086998 ConnectStatusHelper(
6999 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
7000}
7001
bncd16676a2016-07-20 16:23:017002TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:087003 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
7004}
7005
bncd16676a2016-07-20 16:23:017006TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:087007 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
7008}
7009
bncd16676a2016-07-20 16:23:017010TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:087011 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
7012}
7013
bncd16676a2016-07-20 16:23:017014TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:087015 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
7016}
7017
bncd16676a2016-07-20 16:23:017018TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:087019 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
7020}
7021
bncd16676a2016-07-20 16:23:017022TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:087023 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
7024}
7025
bncd16676a2016-07-20 16:23:017026TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087027 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7028}
7029
[email protected]038e9a32008-10-08 22:40:167030// Test the flow when both the proxy server AND origin server require
7031// authentication. Again, this uses basic auth for both since that is
7032// the simplest to mock.
bncd16676a2016-07-20 16:23:017033TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277034 HttpRequestInfo request;
7035 request.method = "GET";
bncce36dca22015-04-21 22:11:237036 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107037 request.traffic_annotation =
7038 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277039
[email protected]038e9a32008-10-08 22:40:167040 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497041 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7042 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097043 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077044
bnc691fda62016-08-12 00:43:167045 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167046
[email protected]f9ee6b52008-11-08 06:46:237047 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237048 MockWrite(
7049 "GET http://www.example.org/ HTTP/1.1\r\n"
7050 "Host: www.example.org\r\n"
7051 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237052 };
7053
[email protected]038e9a32008-10-08 22:40:167054 MockRead data_reads1[] = {
7055 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7056 // Give a couple authenticate options (only the middle one is actually
7057 // supported).
[email protected]22927ad2009-09-21 19:56:197058 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167059 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7060 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7061 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7062 // Large content-length -- won't matter, as connection will be reset.
7063 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067064 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167065 };
7066
bnc691fda62016-08-12 00:43:167067 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167068 // request we should be issuing -- the final header line contains the
7069 // proxy's credentials.
7070 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237071 MockWrite(
7072 "GET http://www.example.org/ HTTP/1.1\r\n"
7073 "Host: www.example.org\r\n"
7074 "Proxy-Connection: keep-alive\r\n"
7075 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167076 };
7077
7078 // Now the proxy server lets the request pass through to origin server.
7079 // The origin server responds with a 401.
7080 MockRead data_reads2[] = {
7081 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7082 // Note: We are using the same realm-name as the proxy server. This is
7083 // completely valid, as realms are unique across hosts.
7084 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7085 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7086 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067087 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167088 };
7089
bnc691fda62016-08-12 00:43:167090 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167091 // the credentials for both the proxy and origin server.
7092 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237093 MockWrite(
7094 "GET http://www.example.org/ HTTP/1.1\r\n"
7095 "Host: www.example.org\r\n"
7096 "Proxy-Connection: keep-alive\r\n"
7097 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7098 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167099 };
7100
7101 // Lastly we get the desired content.
7102 MockRead data_reads3[] = {
7103 MockRead("HTTP/1.0 200 OK\r\n"),
7104 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7105 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067106 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167107 };
7108
Ryan Sleevib8d7ea02018-05-07 20:01:017109 StaticSocketDataProvider data1(data_reads1, data_writes1);
7110 StaticSocketDataProvider data2(data_reads2, data_writes2);
7111 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077112 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7113 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7114 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167115
[email protected]49639fa2011-12-20 23:22:417116 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167117
tfarina42834112016-09-22 13:38:207118 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017119 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167120
7121 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017122 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167123
bnc691fda62016-08-12 00:43:167124 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527125 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587126 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167127
[email protected]49639fa2011-12-20 23:22:417128 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167129
bnc691fda62016-08-12 00:43:167130 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017131 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167132
7133 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017134 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167135
bnc691fda62016-08-12 00:43:167136 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527137 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587138 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167139
[email protected]49639fa2011-12-20 23:22:417140 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167141
bnc691fda62016-08-12 00:43:167142 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7143 callback3.callback());
robpercival214763f2016-07-01 23:27:017144 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167145
7146 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017147 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167148
bnc691fda62016-08-12 00:43:167149 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587150 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167151 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167152}
[email protected]4ddaf2502008-10-23 18:26:197153
[email protected]ea9dc9a2009-09-05 00:43:327154// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7155// can't hook into its internals to cause it to generate predictable NTLM
7156// authorization headers.
7157#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377158// The NTLM authentication unit tests are based on known test data from the
7159// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7160// flow rather than the implementation of the NTLM protocol. See net/ntlm
7161// for the implementation and testing of the protocol.
7162//
7163// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297164
7165// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557166TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427167 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247168 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557169 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:107170 request.traffic_annotation =
7171 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547172
7173 // Ensure load is not disrupted by flags which suppress behaviour specific
7174 // to other auth schemes.
7175 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247176
Zentaro Kavanagh6ccee512017-09-28 18:34:097177 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7178 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097179 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277180
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377181 // Generate the NTLM messages based on known test data.
7182 std::string negotiate_msg;
7183 std::string challenge_msg;
7184 std::string authenticate_msg;
7185 base::Base64Encode(
7186 base::StringPiece(
7187 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247188 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377189 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557190 base::Base64Encode(
7191 base::StringPiece(
7192 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247193 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557194 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377195 base::Base64Encode(
7196 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097197 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557198 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247199 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557200 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377201 &authenticate_msg);
7202
[email protected]3f918782009-02-28 01:29:247203 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557204 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7205 "Host: server\r\n"
7206 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247207 };
7208
7209 MockRead data_reads1[] = {
7210 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047211 // Negotiate and NTLM are often requested together. However, we only want
7212 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7213 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247214 MockRead("WWW-Authenticate: NTLM\r\n"),
7215 MockRead("Connection: close\r\n"),
7216 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367217 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247218 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247219 };
7220
7221 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167222 // After restarting with a null identity, this is the
7223 // request we should be issuing -- the final header line contains a Type
7224 // 1 message.
7225 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557226 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167227 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377228 "Authorization: NTLM "),
7229 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247230
bnc691fda62016-08-12 00:43:167231 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377232 // (using correct credentials). The second request continues on the
7233 // same connection.
bnc691fda62016-08-12 00:43:167234 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557235 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167236 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377237 "Authorization: NTLM "),
7238 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247239 };
7240
7241 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027242 // The origin server responds with a Type 2 message.
7243 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377244 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7245 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027246 MockRead("Content-Type: text/html\r\n\r\n"),
7247 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247248
Bence Béky1e4ef192017-09-18 19:58:027249 // Lastly we get the desired content.
7250 MockRead("HTTP/1.1 200 OK\r\n"),
7251 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7252 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247253 };
7254
Ryan Sleevib8d7ea02018-05-07 20:01:017255 StaticSocketDataProvider data1(data_reads1, data_writes1);
7256 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077257 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7258 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247259
Bence Béky83eb3512017-09-05 12:56:097260 SSLSocketDataProvider ssl1(ASYNC, OK);
7261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7262 SSLSocketDataProvider ssl2(ASYNC, OK);
7263 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7264
[email protected]49639fa2011-12-20 23:22:417265 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247266
bnc691fda62016-08-12 00:43:167267 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507268
tfarina42834112016-09-22 13:38:207269 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017270 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247271
7272 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017273 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247274
bnc691fda62016-08-12 00:43:167275 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227276
bnc691fda62016-08-12 00:43:167277 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527278 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587279 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247280
[email protected]49639fa2011-12-20 23:22:417281 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257282
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377283 rv = trans.RestartWithAuth(
7284 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7285 callback2.callback());
robpercival214763f2016-07-01 23:27:017286 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257287
7288 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017289 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257290
bnc691fda62016-08-12 00:43:167291 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257292
bnc691fda62016-08-12 00:43:167293 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527294 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587295 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257296
[email protected]49639fa2011-12-20 23:22:417297 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247298
bnc691fda62016-08-12 00:43:167299 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017300 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247301
[email protected]0757e7702009-03-27 04:00:227302 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017303 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247304
bnc691fda62016-08-12 00:43:167305 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527306 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587307 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027308 EXPECT_EQ(14, response->headers->GetContentLength());
7309
7310 std::string response_data;
7311 rv = ReadTransaction(&trans, &response_data);
7312 EXPECT_THAT(rv, IsOk());
7313 EXPECT_EQ("Please Login\r\n", response_data);
7314
7315 EXPECT_TRUE(data1.AllReadDataConsumed());
7316 EXPECT_TRUE(data1.AllWriteDataConsumed());
7317 EXPECT_TRUE(data2.AllReadDataConsumed());
7318 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247319}
7320
[email protected]385a4672009-03-11 22:21:297321// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557322TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427323 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297324 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557325 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e2018-02-07 07:41:107326 request.traffic_annotation =
7327 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297328
Zentaro Kavanagh6ccee512017-09-28 18:34:097329 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7330 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097331 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277332
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377333 // Generate the NTLM messages based on known test data.
7334 std::string negotiate_msg;
7335 std::string challenge_msg;
7336 std::string authenticate_msg;
7337 base::Base64Encode(
7338 base::StringPiece(
7339 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247340 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377341 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557342 base::Base64Encode(
7343 base::StringPiece(
7344 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247345 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557346 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377347 base::Base64Encode(
7348 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097349 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557350 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247351 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557352 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377353 &authenticate_msg);
7354
7355 // The authenticate message when |kWrongPassword| is sent.
7356 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557357 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7358 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7359 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7360 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7361 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7362 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377363
Zentaro Kavanagh1890a3d2018-01-29 19:52:557364 // Sanity check that it's the same length as the correct authenticate message
7365 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377366 ASSERT_EQ(authenticate_msg.length(),
7367 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557368 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377369
[email protected]385a4672009-03-11 22:21:297370 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557371 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7372 "Host: server\r\n"
7373 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297374 };
7375
7376 MockRead data_reads1[] = {
7377 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047378 // Negotiate and NTLM are often requested together. However, we only want
7379 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7380 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297381 MockRead("WWW-Authenticate: NTLM\r\n"),
7382 MockRead("Connection: close\r\n"),
7383 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367384 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297385 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297386 };
7387
7388 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167389 // After restarting with a null identity, this is the
7390 // request we should be issuing -- the final header line contains a Type
7391 // 1 message.
7392 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557393 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167394 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377395 "Authorization: NTLM "),
7396 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297397
bnc691fda62016-08-12 00:43:167398 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377399 // (using incorrect credentials). The second request continues on the
7400 // same connection.
bnc691fda62016-08-12 00:43:167401 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557402 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167403 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377404 "Authorization: NTLM "),
7405 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297406 };
7407
7408 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377409 // The origin server responds with a Type 2 message.
7410 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7411 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7412 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
7413 MockRead("Content-Type: text/html\r\n\r\n"),
7414 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297415
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377416 // Wrong password.
7417 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7418 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
7419 MockRead("Content-Length: 42\r\n"),
7420 MockRead("Content-Type: text/html\r\n\r\n"),
7421 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297422 };
7423
7424 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:167425 // After restarting with a null identity, this is the
7426 // request we should be issuing -- the final header line contains a Type
7427 // 1 message.
7428 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557429 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167430 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377431 "Authorization: NTLM "),
7432 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297433
bnc691fda62016-08-12 00:43:167434 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7435 // (the credentials for the origin server). The second request continues
7436 // on the same connection.
7437 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557438 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167439 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377440 "Authorization: NTLM "),
7441 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297442 };
7443
7444 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:027445 // The origin server responds with a Type 2 message.
7446 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377447 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7448 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027449 MockRead("Content-Type: text/html\r\n\r\n"),
7450 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297451
Bence Béky1e4ef192017-09-18 19:58:027452 // Lastly we get the desired content.
7453 MockRead("HTTP/1.1 200 OK\r\n"),
7454 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7455 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:297456 };
7457
Ryan Sleevib8d7ea02018-05-07 20:01:017458 StaticSocketDataProvider data1(data_reads1, data_writes1);
7459 StaticSocketDataProvider data2(data_reads2, data_writes2);
7460 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077461 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7462 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7463 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:297464
Bence Béky83eb3512017-09-05 12:56:097465 SSLSocketDataProvider ssl1(ASYNC, OK);
7466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7467 SSLSocketDataProvider ssl2(ASYNC, OK);
7468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7469 SSLSocketDataProvider ssl3(ASYNC, OK);
7470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7471
[email protected]49639fa2011-12-20 23:22:417472 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:297473
bnc691fda62016-08-12 00:43:167474 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507475
tfarina42834112016-09-22 13:38:207476 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017477 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297478
7479 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017480 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297481
bnc691fda62016-08-12 00:43:167482 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:297483
bnc691fda62016-08-12 00:43:167484 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527485 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587486 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:297487
[email protected]49639fa2011-12-20 23:22:417488 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:297489
[email protected]0757e7702009-03-27 04:00:227490 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377491 rv = trans.RestartWithAuth(
7492 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
7493 callback2.callback());
robpercival214763f2016-07-01 23:27:017494 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297495
[email protected]10af5fe72011-01-31 16:17:257496 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017497 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297498
bnc691fda62016-08-12 00:43:167499 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417500 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:167501 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017502 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257503 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017504 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:167505 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227506
bnc691fda62016-08-12 00:43:167507 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527508 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587509 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:227510
[email protected]49639fa2011-12-20 23:22:417511 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:227512
7513 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377514 rv = trans.RestartWithAuth(
7515 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7516 callback4.callback());
robpercival214763f2016-07-01 23:27:017517 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257518
7519 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:017520 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257521
bnc691fda62016-08-12 00:43:167522 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257523
[email protected]49639fa2011-12-20 23:22:417524 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:257525
7526 // One more roundtrip
bnc691fda62016-08-12 00:43:167527 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:017528 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227529
7530 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:017531 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227532
bnc691fda62016-08-12 00:43:167533 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587534 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027535 EXPECT_EQ(14, response->headers->GetContentLength());
7536
7537 std::string response_data;
7538 rv = ReadTransaction(&trans, &response_data);
7539 EXPECT_THAT(rv, IsOk());
7540 EXPECT_EQ("Please Login\r\n", response_data);
7541
7542 EXPECT_TRUE(data1.AllReadDataConsumed());
7543 EXPECT_TRUE(data1.AllWriteDataConsumed());
7544 EXPECT_TRUE(data2.AllReadDataConsumed());
7545 EXPECT_TRUE(data2.AllWriteDataConsumed());
7546 EXPECT_TRUE(data3.AllReadDataConsumed());
7547 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:297548}
Bence Béky83eb3512017-09-05 12:56:097549
Bence Béky3238f2e12017-09-22 22:44:497550// Server requests NTLM authentication, which is not supported over HTTP/2.
7551// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:097552TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:097553 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7554 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:097555
Zentaro Kavanagh1890a3d2018-01-29 19:52:557556 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:097557
7558 HttpRequestInfo request;
7559 request.method = "GET";
7560 request.url = GURL(kUrl);
Ramin Halavatib5e433e2018-02-07 07:41:107561 request.traffic_annotation =
7562 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:097563
7564 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:137565 spdy::SpdyHeaderBlock request_headers0(
7566 spdy_util_.ConstructGetHeaderBlock(kUrl));
7567 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:097568 1, std::move(request_headers0), LOWEST, true));
7569
Ryan Hamilton0239aac2018-05-19 00:03:137570 spdy::SpdyHeaderBlock response_headers0;
7571 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:097572 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:137573 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:097574 1, std::move(response_headers0), true));
7575
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377576 // Stream 1 is closed.
7577 spdy_util_.UpdateWithStreamDestruction(1);
7578
7579 // Generate the NTLM messages based on known test data.
7580 std::string negotiate_msg;
7581 std::string challenge_msg;
7582 std::string authenticate_msg;
7583 base::Base64Encode(
7584 base::StringPiece(
7585 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247586 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377587 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557588 base::Base64Encode(
7589 base::StringPiece(
7590 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247591 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557592 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377593 base::Base64Encode(
7594 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097595 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557596 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247597 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557598 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377599 &authenticate_msg);
7600
7601 // Retry with authorization header.
Ryan Hamilton0239aac2018-05-19 00:03:137602 spdy::SpdyHeaderBlock request_headers1(
7603 spdy_util_.ConstructGetHeaderBlock(kUrl));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377604 request_headers1["authorization"] = std::string("NTLM ") + negotiate_msg;
Ryan Hamilton0239aac2018-05-19 00:03:137605 spdy::SpdySerializedFrame request1(spdy_util_.ConstructSpdyHeaders(
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377606 3, std::move(request_headers1), LOWEST, true));
7607
Ryan Hamilton0239aac2018-05-19 00:03:137608 spdy::SpdySerializedFrame rst(
7609 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377610
Bence Béky3238f2e12017-09-22 22:44:497611 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
7612 MockRead reads0[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)};
Bence Béky83eb3512017-09-05 12:56:097613
7614 // Retry yet again using HTTP/1.1.
7615 MockWrite writes1[] = {
7616 // After restarting with a null identity, this is the
7617 // request we should be issuing -- the final header line contains a Type
7618 // 1 message.
7619 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557620 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097621 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377622 "Authorization: NTLM "),
7623 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097624
7625 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7626 // (the credentials for the origin server). The second request continues
7627 // on the same connection.
7628 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557629 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097630 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377631 "Authorization: NTLM "),
7632 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097633 };
7634
7635 MockRead reads1[] = {
7636 // The origin server responds with a Type 2 message.
7637 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377638 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7639 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:097640 MockRead("Content-Type: text/html\r\n\r\n"),
7641 MockRead("You are not authorized to view this page\r\n"),
7642
7643 // Lastly we get the desired content.
7644 MockRead("HTTP/1.1 200 OK\r\n"),
7645 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027646 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:097647 };
Ryan Sleevib8d7ea02018-05-07 20:01:017648 SequencedSocketData data0(reads0, writes0);
7649 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:097650 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7651 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7652
7653 SSLSocketDataProvider ssl0(ASYNC, OK);
7654 ssl0.next_proto = kProtoHTTP2;
7655 SSLSocketDataProvider ssl1(ASYNC, OK);
7656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7657 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7658
7659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7660 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7661
7662 TestCompletionCallback callback1;
7663 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
7664 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7665
7666 rv = callback1.WaitForResult();
7667 EXPECT_THAT(rv, IsOk());
7668
7669 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7670
7671 const HttpResponseInfo* response = trans.GetResponseInfo();
7672 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587673 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:097674
7675 TestCompletionCallback callback2;
7676
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377677 rv = trans.RestartWithAuth(
7678 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7679 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:097680 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7681
7682 rv = callback2.WaitForResult();
7683 EXPECT_THAT(rv, IsOk());
7684
7685 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7686
7687 response = trans.GetResponseInfo();
7688 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587689 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:097690
7691 TestCompletionCallback callback3;
7692
7693 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
7694 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7695
7696 rv = callback3.WaitForResult();
7697 EXPECT_THAT(rv, IsOk());
7698
7699 response = trans.GetResponseInfo();
7700 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587701 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027702 EXPECT_EQ(14, response->headers->GetContentLength());
7703
7704 std::string response_data;
7705 rv = ReadTransaction(&trans, &response_data);
7706 EXPECT_THAT(rv, IsOk());
7707 EXPECT_EQ("Please Login\r\n", response_data);
7708
7709 EXPECT_TRUE(data0.AllReadDataConsumed());
7710 EXPECT_TRUE(data0.AllWriteDataConsumed());
7711 EXPECT_TRUE(data1.AllReadDataConsumed());
7712 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:097713}
David Benjamin5cb91132018-04-06 05:54:497714
7715// Test that, if we have an NTLM proxy and the origin resets the connection, we
7716// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:377717// regression test for https://crbug.com/823387. The version interference probe
7718// has since been removed, but retain the regression test so we can update it if
7719// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:497720TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
7721 // The NTLM test data expects the proxy to be named 'server'. The origin is
7722 // https://origin/.
7723 session_deps_.proxy_resolution_service =
7724 ProxyResolutionService::CreateFixedFromPacResult(
7725 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
7726
7727 SSLConfig config;
David Benjamin5cb91132018-04-06 05:54:497728 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:077729 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:497730
7731 HttpRequestInfo request;
7732 request.method = "GET";
7733 request.url = GURL("https://origin/");
7734 request.traffic_annotation =
7735 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7736
7737 // Ensure load is not disrupted by flags which suppress behaviour specific
7738 // to other auth schemes.
7739 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
7740
7741 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7742 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7743 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7744
7745 // Generate the NTLM messages based on known test data.
7746 std::string negotiate_msg;
7747 std::string challenge_msg;
7748 std::string authenticate_msg;
7749 base::Base64Encode(
7750 base::StringPiece(
7751 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247752 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:497753 &negotiate_msg);
7754 base::Base64Encode(
7755 base::StringPiece(
7756 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247757 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:497758 &challenge_msg);
7759 base::Base64Encode(
7760 base::StringPiece(
7761 reinterpret_cast<const char*>(
7762 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247763 base::size(
David Benjamin5cb91132018-04-06 05:54:497764 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7765 &authenticate_msg);
7766
7767 MockWrite data_writes[] = {
7768 // The initial CONNECT request.
7769 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7770 "Host: origin:443\r\n"
7771 "Proxy-Connection: keep-alive\r\n\r\n"),
7772
7773 // After restarting with an identity.
7774 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7775 "Host: origin:443\r\n"
7776 "Proxy-Connection: keep-alive\r\n"
7777 "Proxy-Authorization: NTLM "),
7778 MockWrite(negotiate_msg.c_str()),
7779 // End headers.
7780 MockWrite("\r\n\r\n"),
7781
7782 // The second restart.
7783 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7784 "Host: origin:443\r\n"
7785 "Proxy-Connection: keep-alive\r\n"
7786 "Proxy-Authorization: NTLM "),
7787 MockWrite(authenticate_msg.c_str()),
7788 // End headers.
7789 MockWrite("\r\n\r\n"),
7790 };
7791
7792 MockRead data_reads[] = {
7793 // The initial NTLM response.
7794 MockRead("HTTP/1.1 407 Access Denied\r\n"
7795 "Content-Length: 0\r\n"
7796 "Proxy-Authenticate: NTLM\r\n\r\n"),
7797
7798 // The NTLM challenge message.
7799 MockRead("HTTP/1.1 407 Access Denied\r\n"
7800 "Content-Length: 0\r\n"
7801 "Proxy-Authenticate: NTLM "),
7802 MockRead(challenge_msg.c_str()),
7803 // End headers.
7804 MockRead("\r\n\r\n"),
7805
7806 // Finally the tunnel is established.
7807 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
7808 };
7809
Ryan Sleevib8d7ea02018-05-07 20:01:017810 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:497811 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:497812 session_deps_.socket_factory->AddSocketDataProvider(&data);
7813 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:497814
7815 // Start the transaction. The proxy responds with an NTLM authentication
7816 // request.
7817 TestCompletionCallback callback;
7818 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7819 int rv = callback.GetResult(
7820 trans.Start(&request, callback.callback(), NetLogWithSource()));
7821
7822 EXPECT_THAT(rv, IsOk());
7823 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7824 const HttpResponseInfo* response = trans.GetResponseInfo();
7825 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587826 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:497827
David Benjamind61bd532019-04-23 21:11:377828 // Configure credentials and restart. The proxy responds with the challenge
7829 // message.
David Benjamin5cb91132018-04-06 05:54:497830 rv = callback.GetResult(trans.RestartWithAuth(
7831 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7832 callback.callback()));
7833 EXPECT_THAT(rv, IsOk());
7834 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7835 response = trans.GetResponseInfo();
7836 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587837 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:497838
David Benjamind61bd532019-04-23 21:11:377839 // Restart once more. The tunnel will be established and then the SSL
7840 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:497841 rv = callback.GetResult(
7842 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
7843 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
7844}
7845
[email protected]ea9dc9a2009-09-05 00:43:327846#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:297847
[email protected]4ddaf2502008-10-23 18:26:197848// Test reading a server response which has only headers, and no body.
7849// After some maximum number of bytes is consumed, the transaction should
7850// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:017851TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:427852 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:197853 request.method = "GET";
bncce36dca22015-04-21 22:11:237854 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107855 request.traffic_annotation =
7856 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:197857
danakj1fd259a02016-04-16 03:17:097858 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:167859 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277860
[email protected]b75b7b2f2009-10-06 00:54:537861 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:437862 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:537863 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:197864
7865 MockRead data_reads[] = {
7866 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:067867 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:197868 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:067869 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:197870 };
Ryan Sleevib8d7ea02018-05-07 20:01:017871 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077872 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:197873
[email protected]49639fa2011-12-20 23:22:417874 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:197875
tfarina42834112016-09-22 13:38:207876 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:197878
7879 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017880 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:197881}
[email protected]f4e426b2008-11-05 00:24:497882
7883// Make sure that we don't try to reuse a TCPClientSocket when failing to
7884// establish tunnel.
7885// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:017886TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:277887 HttpRequestInfo request;
7888 request.method = "GET";
bncce36dca22015-04-21 22:11:237889 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107890 request.traffic_annotation =
7891 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277892
[email protected]f4e426b2008-11-05 00:24:497893 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497894 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7895 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:017896
danakj1fd259a02016-04-16 03:17:097897 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:497898
bnc87dcefc2017-05-25 12:47:587899 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197900 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:497901
[email protected]f4e426b2008-11-05 00:24:497902 // Since we have proxy, should try to establish tunnel.
7903 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:177904 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7905 "Host: www.example.org:443\r\n"
7906 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:497907 };
7908
[email protected]77848d12008-11-14 00:00:227909 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:497910 // connection. Usually a proxy would return 501 (not implemented),
7911 // or 200 (tunnel established).
7912 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:237913 MockRead("HTTP/1.1 404 Not Found\r\n"),
7914 MockRead("Content-Length: 10\r\n\r\n"),
7915 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:497916 };
7917
Ryan Sleevib8d7ea02018-05-07 20:01:017918 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077919 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:497920
[email protected]49639fa2011-12-20 23:22:417921 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:497922
tfarina42834112016-09-22 13:38:207923 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017924 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:497925
7926 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017927 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:497928
[email protected]b4404c02009-04-10 16:38:527929 // Empty the current queue. This is necessary because idle sockets are
7930 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557931 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:527932
[email protected]f4e426b2008-11-05 00:24:497933 // We now check to make sure the TCPClientSocket was not added back to
7934 // the pool.
[email protected]90499482013-06-01 00:39:507935 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497936 trans.reset();
fdoray92e35a72016-06-10 15:54:557937 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:497938 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:507939 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497940}
[email protected]372d34a2008-11-05 21:30:517941
[email protected]1b157c02009-04-21 01:55:407942// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:017943TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:427944 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:407945 request.method = "GET";
bncce36dca22015-04-21 22:11:237946 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:107947 request.traffic_annotation =
7948 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:407949
danakj1fd259a02016-04-16 03:17:097950 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277951
bnc691fda62016-08-12 00:43:167952 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277953
[email protected]1b157c02009-04-21 01:55:407954 MockRead data_reads[] = {
7955 // A part of the response body is received with the response headers.
7956 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
7957 // The rest of the response body is received in two parts.
7958 MockRead("lo"),
7959 MockRead(" world"),
7960 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:067961 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:407962 };
7963
Ryan Sleevib8d7ea02018-05-07 20:01:017964 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077965 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:407966
[email protected]49639fa2011-12-20 23:22:417967 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:407968
tfarina42834112016-09-22 13:38:207969 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017970 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:407971
7972 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017973 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407974
bnc691fda62016-08-12 00:43:167975 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527976 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:407977
wezca1070932016-05-26 20:30:527978 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:407979 std::string status_line = response->headers->GetStatusLine();
7980 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
7981
[email protected]90499482013-06-01 00:39:507982 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407983
7984 std::string response_data;
bnc691fda62016-08-12 00:43:167985 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:017986 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407987 EXPECT_EQ("hello world", response_data);
7988
7989 // Empty the current queue. This is necessary because idle sockets are
7990 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557991 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:407992
7993 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:507994 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407995}
7996
[email protected]76a505b2010-08-25 06:23:007997// Make sure that we recycle a SSL socket after reading all of the response
7998// body.
bncd16676a2016-07-20 16:23:017999TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008000 HttpRequestInfo request;
8001 request.method = "GET";
bncce36dca22015-04-21 22:11:238002 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108003 request.traffic_annotation =
8004 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008005
8006 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238007 MockWrite(
8008 "GET / HTTP/1.1\r\n"
8009 "Host: www.example.org\r\n"
8010 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008011 };
8012
8013 MockRead data_reads[] = {
8014 MockRead("HTTP/1.1 200 OK\r\n"),
8015 MockRead("Content-Length: 11\r\n\r\n"),
8016 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068017 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008018 };
8019
[email protected]8ddf8322012-02-23 18:08:068020 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078021 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008022
Ryan Sleevib8d7ea02018-05-07 20:01:018023 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078024 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008025
[email protected]49639fa2011-12-20 23:22:418026 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008027
danakj1fd259a02016-04-16 03:17:098028 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168029 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008030
tfarina42834112016-09-22 13:38:208031 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008032
robpercival214763f2016-07-01 23:27:018033 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8034 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008035
bnc691fda62016-08-12 00:43:168036 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528037 ASSERT_TRUE(response);
8038 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008039 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8040
[email protected]90499482013-06-01 00:39:508041 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008042
8043 std::string response_data;
bnc691fda62016-08-12 00:43:168044 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018045 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008046 EXPECT_EQ("hello world", response_data);
8047
8048 // Empty the current queue. This is necessary because idle sockets are
8049 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558050 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008051
8052 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238053 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008054}
8055
8056// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8057// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018058TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008059 HttpRequestInfo request;
8060 request.method = "GET";
bncce36dca22015-04-21 22:11:238061 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:108062 request.traffic_annotation =
8063 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008064
8065 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238066 MockWrite(
8067 "GET / HTTP/1.1\r\n"
8068 "Host: www.example.org\r\n"
8069 "Connection: keep-alive\r\n\r\n"),
8070 MockWrite(
8071 "GET / HTTP/1.1\r\n"
8072 "Host: www.example.org\r\n"
8073 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008074 };
8075
8076 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428077 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8078 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008079
[email protected]8ddf8322012-02-23 18:08:068080 SSLSocketDataProvider ssl(ASYNC, OK);
8081 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078082 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8083 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008084
Ryan Sleevib8d7ea02018-05-07 20:01:018085 StaticSocketDataProvider data(data_reads, data_writes);
8086 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078087 session_deps_.socket_factory->AddSocketDataProvider(&data);
8088 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008089
[email protected]49639fa2011-12-20 23:22:418090 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008091
danakj1fd259a02016-04-16 03:17:098092 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588093 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198094 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008095
tfarina42834112016-09-22 13:38:208096 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008097
robpercival214763f2016-07-01 23:27:018098 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8099 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008100
8101 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528102 ASSERT_TRUE(response);
8103 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008104 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8105
[email protected]90499482013-06-01 00:39:508106 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008107
8108 std::string response_data;
8109 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018110 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008111 EXPECT_EQ("hello world", response_data);
8112
8113 // Empty the current queue. This is necessary because idle sockets are
8114 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558115 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008116
8117 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238118 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008119
8120 // Now start the second transaction, which should reuse the previous socket.
8121
bnc87dcefc2017-05-25 12:47:588122 trans =
Jeremy Roman0579ed62017-08-29 15:56:198123 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008124
tfarina42834112016-09-22 13:38:208125 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008126
robpercival214763f2016-07-01 23:27:018127 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8128 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008129
8130 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528131 ASSERT_TRUE(response);
8132 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008133 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8134
[email protected]90499482013-06-01 00:39:508135 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008136
8137 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018138 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008139 EXPECT_EQ("hello world", response_data);
8140
8141 // Empty the current queue. This is necessary because idle sockets are
8142 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558143 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008144
8145 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238146 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008147}
8148
maksim.sisov0adf8592016-07-15 06:25:568149// Grab a socket, use it, and put it back into the pool. Then, make
8150// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018151TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568152 HttpRequestInfo request;
8153 request.method = "GET";
8154 request.url = GURL("http://www.example.org/");
8155 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108156 request.traffic_annotation =
8157 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568158
8159 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8160
bnc691fda62016-08-12 00:43:168161 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568162
8163 MockRead data_reads[] = {
8164 // A part of the response body is received with the response headers.
8165 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8166 // The rest of the response body is received in two parts.
8167 MockRead("lo"), MockRead(" world"),
8168 MockRead("junk"), // Should not be read!!
8169 MockRead(SYNCHRONOUS, OK),
8170 };
8171
Ryan Sleevib8d7ea02018-05-07 20:01:018172 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:568173 session_deps_.socket_factory->AddSocketDataProvider(&data);
8174
8175 TestCompletionCallback callback;
8176
tfarina42834112016-09-22 13:38:208177 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568178 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8179
8180 EXPECT_THAT(callback.GetResult(rv), IsOk());
8181
bnc691fda62016-08-12 00:43:168182 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568183 ASSERT_TRUE(response);
8184 EXPECT_TRUE(response->headers);
8185 std::string status_line = response->headers->GetStatusLine();
8186 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8187
8188 // Make memory critical notification and ensure the transaction still has been
8189 // operating right.
8190 base::MemoryPressureListener::NotifyMemoryPressure(
8191 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8192 base::RunLoop().RunUntilIdle();
8193
8194 // Socket should not be flushed as long as it is not idle.
8195 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8196
8197 std::string response_data;
bnc691fda62016-08-12 00:43:168198 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568199 EXPECT_THAT(rv, IsOk());
8200 EXPECT_EQ("hello world", response_data);
8201
8202 // Empty the current queue. This is necessary because idle sockets are
8203 // added to the connection pool asynchronously with a PostTask.
8204 base::RunLoop().RunUntilIdle();
8205
8206 // We now check to make sure the socket was added back to the pool.
8207 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8208
8209 // Idle sockets should be flushed now.
8210 base::MemoryPressureListener::NotifyMemoryPressure(
8211 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8212 base::RunLoop().RunUntilIdle();
8213
8214 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8215}
8216
yucliu48f235d2018-01-11 00:59:558217// Disable idle socket closing on memory pressure.
8218// Grab a socket, use it, and put it back into the pool. Then, make
8219// low memory notification and ensure the socket pool is NOT flushed.
8220TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
8221 HttpRequestInfo request;
8222 request.method = "GET";
8223 request.url = GURL("http://www.example.org/");
8224 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108225 request.traffic_annotation =
8226 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:558227
8228 // Disable idle socket closing on memory pressure.
8229 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
8230 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8231
8232 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8233
8234 MockRead data_reads[] = {
8235 // A part of the response body is received with the response headers.
8236 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8237 // The rest of the response body is received in two parts.
8238 MockRead("lo"), MockRead(" world"),
8239 MockRead("junk"), // Should not be read!!
8240 MockRead(SYNCHRONOUS, OK),
8241 };
8242
Ryan Sleevib8d7ea02018-05-07 20:01:018243 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:558244 session_deps_.socket_factory->AddSocketDataProvider(&data);
8245
8246 TestCompletionCallback callback;
8247
8248 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
8249 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8250
8251 EXPECT_THAT(callback.GetResult(rv), IsOk());
8252
8253 const HttpResponseInfo* response = trans.GetResponseInfo();
8254 ASSERT_TRUE(response);
8255 EXPECT_TRUE(response->headers);
8256 std::string status_line = response->headers->GetStatusLine();
8257 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8258
8259 // Make memory critical notification and ensure the transaction still has been
8260 // operating right.
8261 base::MemoryPressureListener::NotifyMemoryPressure(
8262 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8263 base::RunLoop().RunUntilIdle();
8264
8265 // Socket should not be flushed as long as it is not idle.
8266 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8267
8268 std::string response_data;
8269 rv = ReadTransaction(&trans, &response_data);
8270 EXPECT_THAT(rv, IsOk());
8271 EXPECT_EQ("hello world", response_data);
8272
8273 // Empty the current queue. This is necessary because idle sockets are
8274 // added to the connection pool asynchronously with a PostTask.
8275 base::RunLoop().RunUntilIdle();
8276
8277 // We now check to make sure the socket was added back to the pool.
8278 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8279
8280 // Idle sockets should NOT be flushed on moderate memory pressure.
8281 base::MemoryPressureListener::NotifyMemoryPressure(
8282 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
8283 base::RunLoop().RunUntilIdle();
8284
8285 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8286
8287 // Idle sockets should NOT be flushed on critical memory pressure.
8288 base::MemoryPressureListener::NotifyMemoryPressure(
8289 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8290 base::RunLoop().RunUntilIdle();
8291
8292 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8293}
8294
maksim.sisov0adf8592016-07-15 06:25:568295// Grab an SSL socket, use it, and put it back into the pool. Then, make
8296// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018297TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568298 HttpRequestInfo request;
8299 request.method = "GET";
8300 request.url = GURL("https://www.example.org/");
8301 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108302 request.traffic_annotation =
8303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568304
8305 MockWrite data_writes[] = {
8306 MockWrite("GET / HTTP/1.1\r\n"
8307 "Host: www.example.org\r\n"
8308 "Connection: keep-alive\r\n\r\n"),
8309 };
8310
8311 MockRead data_reads[] = {
8312 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8313 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
8314
8315 SSLSocketDataProvider ssl(ASYNC, OK);
8316 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8317
Ryan Sleevib8d7ea02018-05-07 20:01:018318 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:568319 session_deps_.socket_factory->AddSocketDataProvider(&data);
8320
8321 TestCompletionCallback callback;
8322
8323 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168324 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568325
Matt Menke9d5e2c92019-02-05 01:42:238326 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:208327 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568328
8329 EXPECT_THAT(callback.GetResult(rv), IsOk());
8330
bnc691fda62016-08-12 00:43:168331 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568332 ASSERT_TRUE(response);
8333 ASSERT_TRUE(response->headers);
8334 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
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
Matt Menke9d5e2c92019-02-05 01:42:238342 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568343
8344 std::string response_data;
bnc691fda62016-08-12 00:43:168345 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568346 EXPECT_THAT(rv, IsOk());
8347 EXPECT_EQ("hello world", response_data);
8348
8349 // Empty the current queue. This is necessary because idle sockets are
8350 // added to the connection pool asynchronously with a PostTask.
8351 base::RunLoop().RunUntilIdle();
8352
8353 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238354 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568355
8356 // Make memory notification once again and ensure idle socket is closed.
8357 base::MemoryPressureListener::NotifyMemoryPressure(
8358 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8359 base::RunLoop().RunUntilIdle();
8360
Matt Menke9d5e2c92019-02-05 01:42:238361 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568362}
8363
[email protected]b4404c02009-04-10 16:38:528364// Make sure that we recycle a socket after a zero-length response.
8365// http://crbug.com/9880
bncd16676a2016-07-20 16:23:018366TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:428367 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:528368 request.method = "GET";
bncce36dca22015-04-21 22:11:238369 request.url = GURL(
8370 "http://www.example.org/csi?v=3&s=web&action=&"
8371 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
8372 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
8373 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e2018-02-07 07:41:108374 request.traffic_annotation =
8375 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:528376
danakj1fd259a02016-04-16 03:17:098377 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278378
[email protected]b4404c02009-04-10 16:38:528379 MockRead data_reads[] = {
8380 MockRead("HTTP/1.1 204 No Content\r\n"
8381 "Content-Length: 0\r\n"
8382 "Content-Type: text/html\r\n\r\n"),
8383 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068384 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:528385 };
8386
Ryan Sleevib8d7ea02018-05-07 20:01:018387 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078388 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:528389
mmenkecc2298e2015-12-07 18:20:188390 // Transaction must be created after the MockReads, so it's destroyed before
8391 // them.
bnc691fda62016-08-12 00:43:168392 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:188393
[email protected]49639fa2011-12-20 23:22:418394 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:528395
tfarina42834112016-09-22 13:38:208396 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018397 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:528398
8399 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018400 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528401
bnc691fda62016-08-12 00:43:168402 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528403 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:528404
wezca1070932016-05-26 20:30:528405 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:528406 std::string status_line = response->headers->GetStatusLine();
8407 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
8408
[email protected]90499482013-06-01 00:39:508409 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528410
8411 std::string response_data;
bnc691fda62016-08-12 00:43:168412 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018413 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528414 EXPECT_EQ("", response_data);
8415
8416 // Empty the current queue. This is necessary because idle sockets are
8417 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558418 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528419
8420 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508421 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528422}
8423
bncd16676a2016-07-20 16:23:018424TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:098425 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:228426 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:198427 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:228428 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:278429
[email protected]1c773ea12009-04-28 19:58:428430 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:518431 // Transaction 1: a GET request that succeeds. The socket is recycled
8432 // after use.
8433 request[0].method = "GET";
8434 request[0].url = GURL("http://www.google.com/");
8435 request[0].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108436 request[0].traffic_annotation =
8437 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518438 // Transaction 2: a POST request. Reuses the socket kept alive from
8439 // transaction 1. The first attempts fails when writing the POST data.
8440 // This causes the transaction to retry with a new socket. The second
8441 // attempt succeeds.
8442 request[1].method = "POST";
8443 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:278444 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:518445 request[1].load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:108446 request[1].traffic_annotation =
8447 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518448
danakj1fd259a02016-04-16 03:17:098449 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:518450
8451 // The first socket is used for transaction 1 and the first attempt of
8452 // transaction 2.
8453
8454 // The response of transaction 1.
8455 MockRead data_reads1[] = {
8456 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
8457 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068458 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518459 };
8460 // The mock write results of transaction 1 and the first attempt of
8461 // transaction 2.
8462 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:068463 MockWrite(SYNCHRONOUS, 64), // GET
8464 MockWrite(SYNCHRONOUS, 93), // POST
8465 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:518466 };
Ryan Sleevib8d7ea02018-05-07 20:01:018467 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:518468
8469 // The second socket is used for the second attempt of transaction 2.
8470
8471 // The response of transaction 2.
8472 MockRead data_reads2[] = {
8473 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
8474 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:068475 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518476 };
8477 // The mock write results of the second attempt of transaction 2.
8478 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:068479 MockWrite(SYNCHRONOUS, 93), // POST
8480 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:518481 };
Ryan Sleevib8d7ea02018-05-07 20:01:018482 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:518483
[email protected]bb88e1d32013-05-03 23:11:078484 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8485 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:518486
thestig9d3bb0c2015-01-24 00:49:518487 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:518488 "hello world", "welcome"
8489 };
8490
8491 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:168492 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:518493
[email protected]49639fa2011-12-20 23:22:418494 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:518495
tfarina42834112016-09-22 13:38:208496 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018497 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:518498
8499 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018500 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518501
bnc691fda62016-08-12 00:43:168502 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528503 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:518504
wezca1070932016-05-26 20:30:528505 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:518506 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8507
8508 std::string response_data;
bnc691fda62016-08-12 00:43:168509 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018510 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518511 EXPECT_EQ(kExpectedResponseData[i], response_data);
8512 }
8513}
[email protected]f9ee6b52008-11-08 06:46:238514
8515// Test the request-challenge-retry sequence for basic auth when there is
8516// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:168517// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:018518TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:428519 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238520 request.method = "GET";
bncce36dca22015-04-21 22:11:238521 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:418522 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:108523 request.traffic_annotation =
8524 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:298525
danakj1fd259a02016-04-16 03:17:098526 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168527 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278528
[email protected]a97cca42009-08-14 01:00:298529 // The password contains an escaped character -- for this test to pass it
8530 // will need to be unescaped by HttpNetworkTransaction.
8531 EXPECT_EQ("b%40r", request.url.password());
8532
[email protected]f9ee6b52008-11-08 06:46:238533 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238534 MockWrite(
8535 "GET / HTTP/1.1\r\n"
8536 "Host: www.example.org\r\n"
8537 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238538 };
8539
8540 MockRead data_reads1[] = {
8541 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8542 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8543 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068544 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238545 };
8546
[email protected]2262e3a2012-05-22 16:08:168547 // After the challenge above, the transaction will be restarted using the
8548 // identity from the url (foo, b@r) to answer the challenge.
8549 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238550 MockWrite(
8551 "GET / HTTP/1.1\r\n"
8552 "Host: www.example.org\r\n"
8553 "Connection: keep-alive\r\n"
8554 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168555 };
8556
8557 MockRead data_reads2[] = {
8558 MockRead("HTTP/1.0 200 OK\r\n"),
8559 MockRead("Content-Length: 100\r\n\r\n"),
8560 MockRead(SYNCHRONOUS, OK),
8561 };
8562
Ryan Sleevib8d7ea02018-05-07 20:01:018563 StaticSocketDataProvider data1(data_reads1, data_writes1);
8564 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078565 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8566 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238567
[email protected]49639fa2011-12-20 23:22:418568 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208569 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018570 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238571 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018572 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168573 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168574
8575 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168576 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018577 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168578 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018579 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168580 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228581
bnc691fda62016-08-12 00:43:168582 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528583 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168584
8585 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:588586 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168587
8588 EXPECT_EQ(100, response->headers->GetContentLength());
8589
8590 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558591 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:168592}
8593
8594// Test the request-challenge-retry sequence for basic auth when there is an
8595// incorrect identity in the URL. The identity from the URL should be used only
8596// once.
bncd16676a2016-07-20 16:23:018597TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:168598 HttpRequestInfo request;
8599 request.method = "GET";
8600 // Note: the URL has a username:password in it. The password "baz" is
8601 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:238602 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:168603
8604 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:108605 request.traffic_annotation =
8606 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:168607
danakj1fd259a02016-04-16 03:17:098608 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168609 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:168610
8611 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238612 MockWrite(
8613 "GET / HTTP/1.1\r\n"
8614 "Host: www.example.org\r\n"
8615 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168616 };
8617
8618 MockRead data_reads1[] = {
8619 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8620 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8621 MockRead("Content-Length: 10\r\n\r\n"),
8622 MockRead(SYNCHRONOUS, ERR_FAILED),
8623 };
8624
8625 // After the challenge above, the transaction will be restarted using the
8626 // identity from the url (foo, baz) to answer the challenge.
8627 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238628 MockWrite(
8629 "GET / HTTP/1.1\r\n"
8630 "Host: www.example.org\r\n"
8631 "Connection: keep-alive\r\n"
8632 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168633 };
8634
8635 MockRead data_reads2[] = {
8636 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8637 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8638 MockRead("Content-Length: 10\r\n\r\n"),
8639 MockRead(SYNCHRONOUS, ERR_FAILED),
8640 };
8641
8642 // After the challenge above, the transaction will be restarted using the
8643 // identity supplied by the user (foo, bar) to answer the challenge.
8644 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238645 MockWrite(
8646 "GET / HTTP/1.1\r\n"
8647 "Host: www.example.org\r\n"
8648 "Connection: keep-alive\r\n"
8649 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168650 };
8651
8652 MockRead data_reads3[] = {
8653 MockRead("HTTP/1.0 200 OK\r\n"),
8654 MockRead("Content-Length: 100\r\n\r\n"),
8655 MockRead(SYNCHRONOUS, OK),
8656 };
8657
Ryan Sleevib8d7ea02018-05-07 20:01:018658 StaticSocketDataProvider data1(data_reads1, data_writes1);
8659 StaticSocketDataProvider data2(data_reads2, data_writes2);
8660 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078661 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8662 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8663 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:168664
8665 TestCompletionCallback callback1;
8666
tfarina42834112016-09-22 13:38:208667 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018668 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168669
8670 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018671 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:168672
bnc691fda62016-08-12 00:43:168673 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168674 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168675 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018676 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168677 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018678 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168679 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168680
bnc691fda62016-08-12 00:43:168681 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528682 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588683 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:168684
8685 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168686 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018687 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168688 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018689 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168690 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168691
bnc691fda62016-08-12 00:43:168692 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528693 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168694
8695 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588696 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168697
8698 EXPECT_EQ(100, response->headers->GetContentLength());
8699
[email protected]ea9dc9a2009-09-05 00:43:328700 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558701 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:328702}
8703
[email protected]2217aa22013-10-11 03:03:548704
8705// Test the request-challenge-retry sequence for basic auth when there is a
8706// correct identity in the URL, but its use is being suppressed. The identity
8707// from the URL should never be used.
bncd16676a2016-07-20 16:23:018708TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:548709 HttpRequestInfo request;
8710 request.method = "GET";
bncce36dca22015-04-21 22:11:238711 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:548712 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e2018-02-07 07:41:108713 request.traffic_annotation =
8714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548715
danakj1fd259a02016-04-16 03:17:098716 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168717 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:548718
8719 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238720 MockWrite(
8721 "GET / HTTP/1.1\r\n"
8722 "Host: www.example.org\r\n"
8723 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548724 };
8725
8726 MockRead data_reads1[] = {
8727 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8728 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8729 MockRead("Content-Length: 10\r\n\r\n"),
8730 MockRead(SYNCHRONOUS, ERR_FAILED),
8731 };
8732
8733 // After the challenge above, the transaction will be restarted using the
8734 // identity supplied by the user, not the one in the URL, to answer the
8735 // challenge.
8736 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238737 MockWrite(
8738 "GET / HTTP/1.1\r\n"
8739 "Host: www.example.org\r\n"
8740 "Connection: keep-alive\r\n"
8741 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548742 };
8743
8744 MockRead data_reads3[] = {
8745 MockRead("HTTP/1.0 200 OK\r\n"),
8746 MockRead("Content-Length: 100\r\n\r\n"),
8747 MockRead(SYNCHRONOUS, OK),
8748 };
8749
Ryan Sleevib8d7ea02018-05-07 20:01:018750 StaticSocketDataProvider data1(data_reads1, data_writes1);
8751 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:548752 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8753 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8754
8755 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208756 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018757 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548758 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018759 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168760 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548761
bnc691fda62016-08-12 00:43:168762 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528763 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588764 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:548765
8766 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168767 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018768 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548769 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018770 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168771 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548772
bnc691fda62016-08-12 00:43:168773 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528774 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:548775
8776 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588777 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:548778 EXPECT_EQ(100, response->headers->GetContentLength());
8779
8780 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558781 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:548782}
8783
[email protected]f9ee6b52008-11-08 06:46:238784// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:018785TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:098786 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:238787
8788 // Transaction 1: authenticate (foo, bar) on MyRealm1
8789 {
[email protected]1c773ea12009-04-28 19:58:428790 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238791 request.method = "GET";
bncce36dca22015-04-21 22:11:238792 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:108793 request.traffic_annotation =
8794 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238795
bnc691fda62016-08-12 00:43:168796 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278797
[email protected]f9ee6b52008-11-08 06:46:238798 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238799 MockWrite(
8800 "GET /x/y/z HTTP/1.1\r\n"
8801 "Host: www.example.org\r\n"
8802 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238803 };
8804
8805 MockRead data_reads1[] = {
8806 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8807 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8808 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068809 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238810 };
8811
8812 // Resend with authorization (username=foo, password=bar)
8813 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238814 MockWrite(
8815 "GET /x/y/z HTTP/1.1\r\n"
8816 "Host: www.example.org\r\n"
8817 "Connection: keep-alive\r\n"
8818 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238819 };
8820
8821 // Sever accepts the authorization.
8822 MockRead data_reads2[] = {
8823 MockRead("HTTP/1.0 200 OK\r\n"),
8824 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068825 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238826 };
8827
Ryan Sleevib8d7ea02018-05-07 20:01:018828 StaticSocketDataProvider data1(data_reads1, data_writes1);
8829 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078830 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8831 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238832
[email protected]49639fa2011-12-20 23:22:418833 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238834
tfarina42834112016-09-22 13:38:208835 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018836 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238837
8838 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018839 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238840
bnc691fda62016-08-12 00:43:168841 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528842 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588843 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:238844
[email protected]49639fa2011-12-20 23:22:418845 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238846
bnc691fda62016-08-12 00:43:168847 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
8848 callback2.callback());
robpercival214763f2016-07-01 23:27:018849 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238850
8851 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018852 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238853
bnc691fda62016-08-12 00:43:168854 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528855 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588856 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238857 EXPECT_EQ(100, response->headers->GetContentLength());
8858 }
8859
8860 // ------------------------------------------------------------------------
8861
8862 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
8863 {
[email protected]1c773ea12009-04-28 19:58:428864 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238865 request.method = "GET";
8866 // Note that Transaction 1 was at /x/y/z, so this is in the same
8867 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:238868 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:108869 request.traffic_annotation =
8870 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238871
bnc691fda62016-08-12 00:43:168872 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278873
[email protected]f9ee6b52008-11-08 06:46:238874 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238875 MockWrite(
8876 "GET /x/y/a/b HTTP/1.1\r\n"
8877 "Host: www.example.org\r\n"
8878 "Connection: keep-alive\r\n"
8879 // Send preemptive authorization for MyRealm1
8880 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238881 };
8882
8883 // The server didn't like the preemptive authorization, and
8884 // challenges us for a different realm (MyRealm2).
8885 MockRead data_reads1[] = {
8886 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8887 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
8888 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068889 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238890 };
8891
8892 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
8893 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238894 MockWrite(
8895 "GET /x/y/a/b HTTP/1.1\r\n"
8896 "Host: www.example.org\r\n"
8897 "Connection: keep-alive\r\n"
8898 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238899 };
8900
8901 // Sever accepts the authorization.
8902 MockRead data_reads2[] = {
8903 MockRead("HTTP/1.0 200 OK\r\n"),
8904 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068905 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238906 };
8907
Ryan Sleevib8d7ea02018-05-07 20:01:018908 StaticSocketDataProvider data1(data_reads1, data_writes1);
8909 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078910 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8911 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238912
[email protected]49639fa2011-12-20 23:22:418913 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238914
tfarina42834112016-09-22 13:38:208915 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018916 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238917
8918 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018919 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238920
bnc691fda62016-08-12 00:43:168921 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528922 ASSERT_TRUE(response);
8923 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:048924 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:438925 EXPECT_EQ("http://www.example.org",
8926 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:048927 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:198928 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:238929
[email protected]49639fa2011-12-20 23:22:418930 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238931
bnc691fda62016-08-12 00:43:168932 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
8933 callback2.callback());
robpercival214763f2016-07-01 23:27:018934 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238935
8936 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018937 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238938
bnc691fda62016-08-12 00:43:168939 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528940 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588941 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238942 EXPECT_EQ(100, response->headers->GetContentLength());
8943 }
8944
8945 // ------------------------------------------------------------------------
8946
8947 // Transaction 3: Resend a request in MyRealm's protection space --
8948 // succeed with preemptive authorization.
8949 {
[email protected]1c773ea12009-04-28 19:58:428950 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238951 request.method = "GET";
bncce36dca22015-04-21 22:11:238952 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e2018-02-07 07:41:108953 request.traffic_annotation =
8954 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238955
bnc691fda62016-08-12 00:43:168956 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278957
[email protected]f9ee6b52008-11-08 06:46:238958 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238959 MockWrite(
8960 "GET /x/y/z2 HTTP/1.1\r\n"
8961 "Host: www.example.org\r\n"
8962 "Connection: keep-alive\r\n"
8963 // The authorization for MyRealm1 gets sent preemptively
8964 // (since the url is in the same protection space)
8965 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238966 };
8967
8968 // Sever accepts the preemptive authorization
8969 MockRead data_reads1[] = {
8970 MockRead("HTTP/1.0 200 OK\r\n"),
8971 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068972 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238973 };
8974
Ryan Sleevib8d7ea02018-05-07 20:01:018975 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078976 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:238977
[email protected]49639fa2011-12-20 23:22:418978 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238979
tfarina42834112016-09-22 13:38:208980 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018981 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238982
8983 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018984 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238985
bnc691fda62016-08-12 00:43:168986 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528987 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:238988
Emily Starkf2c9bbd2019-04-09 17:08:588989 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238990 EXPECT_EQ(100, response->headers->GetContentLength());
8991 }
8992
8993 // ------------------------------------------------------------------------
8994
8995 // Transaction 4: request another URL in MyRealm (however the
8996 // url is not known to belong to the protection space, so no pre-auth).
8997 {
[email protected]1c773ea12009-04-28 19:58:428998 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238999 request.method = "GET";
bncce36dca22015-04-21 22:11:239000 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e2018-02-07 07:41:109001 request.traffic_annotation =
9002 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239003
bnc691fda62016-08-12 00:43:169004 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279005
[email protected]f9ee6b52008-11-08 06:46:239006 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239007 MockWrite(
9008 "GET /x/1 HTTP/1.1\r\n"
9009 "Host: www.example.org\r\n"
9010 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239011 };
9012
9013 MockRead data_reads1[] = {
9014 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9015 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9016 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069017 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239018 };
9019
9020 // Resend with authorization from MyRealm's cache.
9021 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239022 MockWrite(
9023 "GET /x/1 HTTP/1.1\r\n"
9024 "Host: www.example.org\r\n"
9025 "Connection: keep-alive\r\n"
9026 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239027 };
9028
9029 // Sever accepts the authorization.
9030 MockRead data_reads2[] = {
9031 MockRead("HTTP/1.0 200 OK\r\n"),
9032 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069033 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239034 };
9035
Ryan Sleevib8d7ea02018-05-07 20:01:019036 StaticSocketDataProvider data1(data_reads1, data_writes1);
9037 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079038 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9039 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239040
[email protected]49639fa2011-12-20 23:22:419041 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239042
tfarina42834112016-09-22 13:38:209043 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019044 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239045
9046 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019047 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239048
bnc691fda62016-08-12 00:43:169049 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419050 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169051 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019052 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229053 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019054 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169055 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229056
bnc691fda62016-08-12 00:43:169057 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529058 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589059 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239060 EXPECT_EQ(100, response->headers->GetContentLength());
9061 }
9062
9063 // ------------------------------------------------------------------------
9064
9065 // Transaction 5: request a URL in MyRealm, but the server rejects the
9066 // cached identity. Should invalidate and re-prompt.
9067 {
[email protected]1c773ea12009-04-28 19:58:429068 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239069 request.method = "GET";
bncce36dca22015-04-21 22:11:239070 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e2018-02-07 07:41:109071 request.traffic_annotation =
9072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239073
bnc691fda62016-08-12 00:43:169074 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279075
[email protected]f9ee6b52008-11-08 06:46:239076 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239077 MockWrite(
9078 "GET /p/q/t HTTP/1.1\r\n"
9079 "Host: www.example.org\r\n"
9080 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239081 };
9082
9083 MockRead data_reads1[] = {
9084 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9085 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9086 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069087 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239088 };
9089
9090 // Resend with authorization from cache for MyRealm.
9091 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239092 MockWrite(
9093 "GET /p/q/t HTTP/1.1\r\n"
9094 "Host: www.example.org\r\n"
9095 "Connection: keep-alive\r\n"
9096 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239097 };
9098
9099 // Sever rejects the authorization.
9100 MockRead data_reads2[] = {
9101 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9102 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9103 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069104 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239105 };
9106
9107 // At this point we should prompt for new credentials for MyRealm.
9108 // Restart with username=foo3, password=foo4.
9109 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239110 MockWrite(
9111 "GET /p/q/t HTTP/1.1\r\n"
9112 "Host: www.example.org\r\n"
9113 "Connection: keep-alive\r\n"
9114 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239115 };
9116
9117 // Sever accepts the authorization.
9118 MockRead data_reads3[] = {
9119 MockRead("HTTP/1.0 200 OK\r\n"),
9120 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069121 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239122 };
9123
Ryan Sleevib8d7ea02018-05-07 20:01:019124 StaticSocketDataProvider data1(data_reads1, data_writes1);
9125 StaticSocketDataProvider data2(data_reads2, data_writes2);
9126 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079127 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9128 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9129 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239130
[email protected]49639fa2011-12-20 23:22:419131 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239132
tfarina42834112016-09-22 13:38:209133 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019134 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239135
9136 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019137 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239138
bnc691fda62016-08-12 00:43:169139 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419140 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169141 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019142 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229143 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019144 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169145 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229146
bnc691fda62016-08-12 00:43:169147 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529148 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589149 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239150
[email protected]49639fa2011-12-20 23:22:419151 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239152
bnc691fda62016-08-12 00:43:169153 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9154 callback3.callback());
robpercival214763f2016-07-01 23:27:019155 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239156
[email protected]0757e7702009-03-27 04:00:229157 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019158 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239159
bnc691fda62016-08-12 00:43:169160 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529161 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589162 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239163 EXPECT_EQ(100, response->headers->GetContentLength());
9164 }
9165}
[email protected]89ceba9a2009-03-21 03:46:069166
[email protected]3c32c5f2010-05-18 15:18:129167// Tests that nonce count increments when multiple auth attempts
9168// are started with the same nonce.
bncd16676a2016-07-20 16:23:019169TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449170 HttpAuthHandlerDigest::Factory* digest_factory =
9171 new HttpAuthHandlerDigest::Factory();
9172 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
9173 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
9174 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:079175 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:099176 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:129177
9178 // Transaction 1: authenticate (foo, bar) on MyRealm1
9179 {
[email protected]3c32c5f2010-05-18 15:18:129180 HttpRequestInfo request;
9181 request.method = "GET";
bncce36dca22015-04-21 22:11:239182 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e2018-02-07 07:41:109183 request.traffic_annotation =
9184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129185
bnc691fda62016-08-12 00:43:169186 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279187
[email protected]3c32c5f2010-05-18 15:18:129188 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239189 MockWrite(
9190 "GET /x/y/z HTTP/1.1\r\n"
9191 "Host: www.example.org\r\n"
9192 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129193 };
9194
9195 MockRead data_reads1[] = {
9196 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9197 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
9198 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069199 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129200 };
9201
9202 // Resend with authorization (username=foo, password=bar)
9203 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239204 MockWrite(
9205 "GET /x/y/z HTTP/1.1\r\n"
9206 "Host: www.example.org\r\n"
9207 "Connection: keep-alive\r\n"
9208 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9209 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
9210 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
9211 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129212 };
9213
9214 // Sever accepts the authorization.
9215 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:089216 MockRead("HTTP/1.0 200 OK\r\n"),
9217 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129218 };
9219
Ryan Sleevib8d7ea02018-05-07 20:01:019220 StaticSocketDataProvider data1(data_reads1, data_writes1);
9221 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079222 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9223 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:129224
[email protected]49639fa2011-12-20 23:22:419225 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129226
tfarina42834112016-09-22 13:38:209227 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019228 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129229
9230 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019231 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129232
bnc691fda62016-08-12 00:43:169233 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529234 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589235 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:129236
[email protected]49639fa2011-12-20 23:22:419237 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:129238
bnc691fda62016-08-12 00:43:169239 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9240 callback2.callback());
robpercival214763f2016-07-01 23:27:019241 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129242
9243 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019244 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129245
bnc691fda62016-08-12 00:43:169246 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529247 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589248 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129249 }
9250
9251 // ------------------------------------------------------------------------
9252
9253 // Transaction 2: Request another resource in digestive's protection space.
9254 // This will preemptively add an Authorization header which should have an
9255 // "nc" value of 2 (as compared to 1 in the first use.
9256 {
[email protected]3c32c5f2010-05-18 15:18:129257 HttpRequestInfo request;
9258 request.method = "GET";
9259 // Note that Transaction 1 was at /x/y/z, so this is in the same
9260 // protection space as digest.
bncce36dca22015-04-21 22:11:239261 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e2018-02-07 07:41:109262 request.traffic_annotation =
9263 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129264
bnc691fda62016-08-12 00:43:169265 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279266
[email protected]3c32c5f2010-05-18 15:18:129267 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239268 MockWrite(
9269 "GET /x/y/a/b HTTP/1.1\r\n"
9270 "Host: www.example.org\r\n"
9271 "Connection: keep-alive\r\n"
9272 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9273 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
9274 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
9275 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129276 };
9277
9278 // Sever accepts the authorization.
9279 MockRead data_reads1[] = {
9280 MockRead("HTTP/1.0 200 OK\r\n"),
9281 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069282 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129283 };
9284
Ryan Sleevib8d7ea02018-05-07 20:01:019285 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079286 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:129287
[email protected]49639fa2011-12-20 23:22:419288 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129289
tfarina42834112016-09-22 13:38:209290 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019291 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129292
9293 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019294 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129295
bnc691fda62016-08-12 00:43:169296 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529297 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589298 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129299 }
9300}
9301
[email protected]89ceba9a2009-03-21 03:46:069302// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:019303TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:069304 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:099305 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169306 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:069307
9308 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:449309 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:169310 trans.read_buf_len_ = 15;
9311 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:069312
9313 // Setup state in response_
bnc691fda62016-08-12 00:43:169314 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:589315 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:089316 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:579317 response->response_time = base::Time::Now();
9318 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:069319
9320 { // Setup state for response_.vary_data
9321 HttpRequestInfo request;
9322 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
9323 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:279324 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:439325 request.extra_headers.SetHeader("Foo", "1");
9326 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:509327 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:069328 }
9329
9330 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:169331 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:069332
9333 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:169334 EXPECT_FALSE(trans.read_buf_);
9335 EXPECT_EQ(0, trans.read_buf_len_);
9336 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:589337 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:529338 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:049339 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:089340 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:579341 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:069342}
9343
[email protected]bacff652009-03-31 17:50:339344// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:019345TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:339346 HttpRequestInfo request;
9347 request.method = "GET";
bncce36dca22015-04-21 22:11:239348 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109349 request.traffic_annotation =
9350 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339351
danakj1fd259a02016-04-16 03:17:099352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169353 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279354
[email protected]bacff652009-03-31 17:50:339355 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239356 MockWrite(
9357 "GET / HTTP/1.1\r\n"
9358 "Host: www.example.org\r\n"
9359 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339360 };
9361
9362 MockRead data_reads[] = {
9363 MockRead("HTTP/1.0 200 OK\r\n"),
9364 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9365 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069366 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339367 };
9368
[email protected]5ecc992a42009-11-11 01:41:599369 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:019370 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069371 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9372 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339373
[email protected]bb88e1d32013-05-03 23:11:079374 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9375 session_deps_.socket_factory->AddSocketDataProvider(&data);
9376 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9377 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339378
[email protected]49639fa2011-12-20 23:22:419379 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339380
tfarina42834112016-09-22 13:38:209381 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019382 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339383
9384 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019385 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339386
bnc691fda62016-08-12 00:43:169387 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019388 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339389
9390 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019391 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339392
bnc691fda62016-08-12 00:43:169393 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339394
wezca1070932016-05-26 20:30:529395 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339396 EXPECT_EQ(100, response->headers->GetContentLength());
9397}
9398
9399// Test HTTPS connections to a site with a bad certificate, going through a
9400// proxy
bncd16676a2016-07-20 16:23:019401TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499402 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9403 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339404
9405 HttpRequestInfo request;
9406 request.method = "GET";
bncce36dca22015-04-21 22:11:239407 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109408 request.traffic_annotation =
9409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339410
9411 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:179412 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9413 "Host: www.example.org:443\r\n"
9414 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339415 };
9416
9417 MockRead proxy_reads[] = {
9418 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069419 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:339420 };
9421
9422 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179423 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9424 "Host: www.example.org:443\r\n"
9425 "Proxy-Connection: keep-alive\r\n\r\n"),
9426 MockWrite("GET / HTTP/1.1\r\n"
9427 "Host: www.example.org\r\n"
9428 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339429 };
9430
9431 MockRead data_reads[] = {
9432 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9433 MockRead("HTTP/1.0 200 OK\r\n"),
9434 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9435 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069436 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339437 };
9438
Ryan Sleevib8d7ea02018-05-07 20:01:019439 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
9440 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069441 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9442 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339443
[email protected]bb88e1d32013-05-03 23:11:079444 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9445 session_deps_.socket_factory->AddSocketDataProvider(&data);
9446 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9447 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339448
[email protected]49639fa2011-12-20 23:22:419449 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339450
9451 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:079452 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:339453
danakj1fd259a02016-04-16 03:17:099454 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169455 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:339456
tfarina42834112016-09-22 13:38:209457 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019458 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339459
9460 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019461 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339462
bnc691fda62016-08-12 00:43:169463 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019464 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339465
9466 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019467 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339468
bnc691fda62016-08-12 00:43:169469 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339470
wezca1070932016-05-26 20:30:529471 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339472 EXPECT_EQ(100, response->headers->GetContentLength());
9473 }
9474}
9475
[email protected]2df19bb2010-08-25 20:13:469476
9477// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:019478TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599479 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499480 ProxyResolutionService::CreateFixedFromPacResult(
9481 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519482 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079483 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:469484
9485 HttpRequestInfo request;
9486 request.method = "GET";
bncce36dca22015-04-21 22:11:239487 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109488 request.traffic_annotation =
9489 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:469490
9491 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179492 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9493 "Host: www.example.org:443\r\n"
9494 "Proxy-Connection: keep-alive\r\n\r\n"),
9495 MockWrite("GET / HTTP/1.1\r\n"
9496 "Host: www.example.org\r\n"
9497 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:469498 };
9499
9500 MockRead data_reads[] = {
9501 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9502 MockRead("HTTP/1.1 200 OK\r\n"),
9503 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9504 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069505 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:469506 };
9507
Ryan Sleevib8d7ea02018-05-07 20:01:019508 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069509 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9510 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:469511
[email protected]bb88e1d32013-05-03 23:11:079512 session_deps_.socket_factory->AddSocketDataProvider(&data);
9513 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9514 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:469515
[email protected]49639fa2011-12-20 23:22:419516 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:469517
danakj1fd259a02016-04-16 03:17:099518 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169519 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:469520
tfarina42834112016-09-22 13:38:209521 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019522 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:469523
9524 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019525 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169526 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:469527
wezca1070932016-05-26 20:30:529528 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:469529
tbansal2ecbbc72016-10-06 17:15:479530 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:469531 EXPECT_TRUE(response->headers->IsKeepAlive());
9532 EXPECT_EQ(200, response->headers->response_code());
9533 EXPECT_EQ(100, response->headers->GetContentLength());
9534 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:209535
9536 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:169537 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:209538 TestLoadTimingNotReusedWithPac(load_timing_info,
9539 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:469540}
9541
Eric Roman695a7872019-04-16 21:53:299542// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:019543TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599544 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499545 ProxyResolutionService::CreateFixedFromPacResult(
9546 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519547 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079548 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:299549
Matt Menkeecfecfc72019-02-05 19:15:289550 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9551 session_deps_.host_resolver->set_ondemand_mode(true);
9552
[email protected]511f6f52010-12-17 03:58:299553 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:129554 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:299555 request.method = "GET";
bncce36dca22015-04-21 22:11:239556 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109557 request.traffic_annotation =
9558 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299559
9560 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:289561 MockWrite(ASYNC, 0,
9562 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:179563 "Host: www.example.org:443\r\n"
9564 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299565 };
9566
9567 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289568 // Pause on first read.
9569 MockRead(ASYNC, ERR_IO_PENDING, 1),
9570 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
9571 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
9572 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299573 };
9574
Matt Menkeecfecfc72019-02-05 19:15:289575 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069576 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299577
[email protected]bb88e1d32013-05-03 23:11:079578 session_deps_.socket_factory->AddSocketDataProvider(&data);
9579 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299580
[email protected]49639fa2011-12-20 23:22:419581 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299582
danakj1fd259a02016-04-16 03:17:099583 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169584 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299585
tfarina42834112016-09-22 13:38:209586 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019587 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289588 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
9589
9590 // Host resolution takes |kTimeIncrement|.
9591 FastForwardBy(kTimeIncrement);
9592 // Resolving the current request with |ResolveNow| will cause the pending
9593 // request to instantly complete, and the async connect will start as well.
9594 session_deps_.host_resolver->ResolveOnlyRequestNow();
9595
9596 // Connecting takes |kTimeIncrement|.
9597 FastForwardBy(kTimeIncrement);
9598 data.RunUntilPaused();
9599
9600 // The server takes |kTimeIncrement| to respond.
9601 FastForwardBy(kTimeIncrement);
9602 data.Resume();
[email protected]511f6f52010-12-17 03:58:299603
9604 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599605 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299606}
9607
Eric Roman74103c72019-02-21 00:23:129608// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
9609TEST_F(HttpNetworkTransactionTest,
9610 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
9611 base::HistogramTester histograms;
9612 session_deps_.proxy_resolution_service =
9613 ProxyResolutionService::CreateFixedFromPacResult(
9614 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9615 TestNetLog net_log;
9616 session_deps_.net_log = &net_log;
9617
9618 HttpRequestInfo request;
9619 request.method = "GET";
9620 request.url = GURL("https://www.example.org/");
9621 request.traffic_annotation =
9622 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9623
9624 MockWrite data_writes[] = {
9625 MockWrite(ASYNC, 0,
9626 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9627 "Host: www.example.org:443\r\n"
9628 "Proxy-Connection: keep-alive\r\n\r\n"),
9629 };
9630
9631 MockRead data_reads[] = {
9632 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9633 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9634 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9635 };
9636
9637 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9638 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9639
9640 session_deps_.socket_factory->AddSocketDataProvider(&data);
9641 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9642
9643 TestCompletionCallback callback;
9644
9645 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9646 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9647
9648 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9649 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9650
9651 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599652 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129653}
9654
9655// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
9656// request for main frames.
9657TEST_F(HttpNetworkTransactionTest,
9658 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
9659 base::HistogramTester histograms;
9660 session_deps_.proxy_resolution_service =
9661 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
9662 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9663 TestNetLog net_log;
9664 session_deps_.net_log = &net_log;
9665
9666 HttpRequestInfo request;
9667 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
9668 request.method = "GET";
9669 request.url = GURL("https://www.example.org/");
9670 request.traffic_annotation =
9671 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9672
9673 MockWrite data_writes[] = {
9674 MockWrite(ASYNC, 0,
9675 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9676 "Host: www.example.org:443\r\n"
9677 "Proxy-Connection: keep-alive\r\n\r\n"),
9678 };
9679
9680 MockRead data_reads[] = {
9681 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9682 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9683 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9684 };
9685
9686 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9687 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9688
9689 session_deps_.socket_factory->AddSocketDataProvider(&data);
9690 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9691
9692 TestCompletionCallback callback;
9693
9694 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9695 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9696
9697 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9698 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9699
9700 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599701 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129702}
9703
Eric Roman695a7872019-04-16 21:53:299704// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:129705// frames.
bncd16676a2016-07-20 16:23:019706TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:129707 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:499708 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9709 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:289710 TestNetLog net_log;
9711 session_deps_.net_log = &net_log;
9712
Matt Menkeecfecfc72019-02-05 19:15:289713 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9714 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:299715
9716 HttpRequestInfo request;
9717 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:129718 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:239719 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109720 request.traffic_annotation =
9721 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299722
Ryan Hamilton0239aac2018-05-19 00:03:139723 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049724 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9725 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139726 spdy::SpdySerializedFrame goaway(
9727 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299728 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419729 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:289730 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:299731 };
9732
9733 static const char* const kExtraHeaders[] = {
9734 "location",
9735 "http://login.example.com/",
9736 };
Ryan Hamilton0239aac2018-05-19 00:03:139737 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249738 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:299739 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289740 // Pause on first read.
9741 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
9742 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299743 };
9744
Matt Menkeecfecfc72019-02-05 19:15:289745 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069746 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369747 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299748
[email protected]bb88e1d32013-05-03 23:11:079749 session_deps_.socket_factory->AddSocketDataProvider(&data);
9750 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299751
[email protected]49639fa2011-12-20 23:22:419752 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299753
danakj1fd259a02016-04-16 03:17:099754 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169755 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299756
tfarina42834112016-09-22 13:38:209757 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019758 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289759 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:299760
Matt Menkeecfecfc72019-02-05 19:15:289761 // Host resolution takes |kTimeIncrement|.
9762 FastForwardBy(kTimeIncrement);
9763 // Resolving the current request with |ResolveNow| will cause the pending
9764 // request to instantly complete, and the async connect will start as well.
9765 session_deps_.host_resolver->ResolveOnlyRequestNow();
9766
9767 // Connecting takes |kTimeIncrement|.
9768 FastForwardBy(kTimeIncrement);
9769 data.RunUntilPaused();
9770
9771 FastForwardBy(kTimeIncrement);
9772 data.Resume();
[email protected]511f6f52010-12-17 03:58:299773 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599774 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299775}
9776
[email protected]4eddbc732012-08-09 05:40:179777// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019778TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499779 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9780 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299781
9782 HttpRequestInfo request;
9783 request.method = "GET";
bncce36dca22015-04-21 22:11:239784 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109785 request.traffic_annotation =
9786 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299787
9788 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179789 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9790 "Host: www.example.org:443\r\n"
9791 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299792 };
9793
9794 MockRead data_reads[] = {
9795 MockRead("HTTP/1.1 404 Not Found\r\n"),
9796 MockRead("Content-Length: 23\r\n\r\n"),
9797 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:069798 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:299799 };
9800
Ryan Sleevib8d7ea02018-05-07 20:01:019801 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069802 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299803
[email protected]bb88e1d32013-05-03 23:11:079804 session_deps_.socket_factory->AddSocketDataProvider(&data);
9805 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299806
[email protected]49639fa2011-12-20 23:22:419807 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299808
danakj1fd259a02016-04-16 03:17:099809 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169810 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299811
tfarina42834112016-09-22 13:38:209812 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019813 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299814
9815 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019816 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299817
ttuttle960fcbf2016-04-19 13:26:329818 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299819}
9820
[email protected]4eddbc732012-08-09 05:40:179821// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019822TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499823 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9824 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299825
9826 HttpRequestInfo request;
9827 request.method = "GET";
bncce36dca22015-04-21 22:11:239828 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:109829 request.traffic_annotation =
9830 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299831
Ryan Hamilton0239aac2018-05-19 00:03:139832 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049833 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9834 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139835 spdy::SpdySerializedFrame rst(
9836 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299837 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419838 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:299839 };
9840
9841 static const char* const kExtraHeaders[] = {
9842 "location",
9843 "http://login.example.com/",
9844 };
Ryan Hamilton0239aac2018-05-19 00:03:139845 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249846 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:139847 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:199848 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:299849 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:419850 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:139851 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299852 };
9853
Ryan Sleevib8d7ea02018-05-07 20:01:019854 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069855 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369856 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299857
[email protected]bb88e1d32013-05-03 23:11:079858 session_deps_.socket_factory->AddSocketDataProvider(&data);
9859 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299860
[email protected]49639fa2011-12-20 23:22:419861 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299862
danakj1fd259a02016-04-16 03:17:099863 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169864 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299865
tfarina42834112016-09-22 13:38:209866 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019867 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299868
9869 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019870 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299871
ttuttle960fcbf2016-04-19 13:26:329872 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299873}
9874
[email protected]0c5fb722012-02-28 11:50:359875// Test the request-challenge-retry sequence for basic auth, through
9876// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:019877TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:359878 HttpRequestInfo request;
9879 request.method = "GET";
bncce36dca22015-04-21 22:11:239880 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:359881 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:299882 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e2018-02-07 07:41:109883 request.traffic_annotation =
9884 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:359885
9886 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:599887 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499888 ProxyResolutionService::CreateFixedFromPacResult(
9889 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519890 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:079891 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:099892 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:359893
9894 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:139895 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049896 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9897 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139898 spdy::SpdySerializedFrame rst(
9899 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:389900 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:359901
bnc691fda62016-08-12 00:43:169902 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:359903 // be issuing -- the final header line contains the credentials.
9904 const char* const kAuthCredentials[] = {
9905 "proxy-authorization", "Basic Zm9vOmJhcg==",
9906 };
Ryan Hamilton0239aac2018-05-19 00:03:139907 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049908 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
9909 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:239910 HostPortPair("www.example.org", 443)));
9911 // fetch https://www.example.org/ via HTTP
9912 const char get[] =
9913 "GET / HTTP/1.1\r\n"
9914 "Host: www.example.org\r\n"
9915 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:139916 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:199917 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:359918
9919 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:419920 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
9921 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:359922 };
9923
9924 // The proxy responds to the connect with a 407, using a persistent
9925 // connection.
thestig9d3bb0c2015-01-24 00:49:519926 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:359927 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:359928 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
9929 };
Ryan Hamilton0239aac2018-05-19 00:03:139930 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249931 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:359932
Ryan Hamilton0239aac2018-05-19 00:03:139933 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:359934 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:359935 const char resp[] = "HTTP/1.1 200 OK\r\n"
9936 "Content-Length: 5\r\n\r\n";
9937
Ryan Hamilton0239aac2018-05-19 00:03:139938 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:199939 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:139940 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:199941 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:359942 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:419943 CreateMockRead(conn_auth_resp, 1, ASYNC),
9944 CreateMockRead(conn_resp, 4, ASYNC),
9945 CreateMockRead(wrapped_get_resp, 6, ASYNC),
9946 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:139947 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:359948 };
9949
Ryan Sleevib8d7ea02018-05-07 20:01:019950 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:079951 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:359952 // Negotiate SPDY to the proxy
9953 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:369954 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:079955 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:359956 // Vanilla SSL to the server
9957 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079958 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:359959
9960 TestCompletionCallback callback1;
9961
bnc87dcefc2017-05-25 12:47:589962 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199963 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:359964
9965 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:019966 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359967
9968 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019969 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:469970 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:359971 log.GetEntries(&entries);
9972 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:009973 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9974 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359975 ExpectLogContainsSomewhere(
9976 entries, pos,
mikecirone8b85c432016-09-08 19:11:009977 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9978 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359979
9980 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529981 ASSERT_TRUE(response);
9982 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:359983 EXPECT_EQ(407, response->headers->response_code());
9984 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:589985 EXPECT_TRUE(response->auth_challenge.has_value());
9986 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:359987
9988 TestCompletionCallback callback2;
9989
9990 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
9991 callback2.callback());
robpercival214763f2016-07-01 23:27:019992 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359993
9994 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019995 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:359996
9997 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529998 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:359999
10000 EXPECT_TRUE(response->headers->IsKeepAlive());
10001 EXPECT_EQ(200, response->headers->response_code());
10002 EXPECT_EQ(5, response->headers->GetContentLength());
10003 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10004
10005 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810006 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510007
[email protected]029c83b62013-01-24 05:28:2010008 LoadTimingInfo load_timing_info;
10009 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10010 TestLoadTimingNotReusedWithPac(load_timing_info,
10011 CONNECT_TIMING_HAS_SSL_TIMES);
10012
[email protected]0c5fb722012-02-28 11:50:3510013 trans.reset();
10014 session->CloseAllConnections();
10015}
10016
[email protected]7c6f7ba2012-04-03 04:09:2910017// Test that an explicitly trusted SPDY proxy can push a resource from an
10018// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110019TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510020 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910021 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510022 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10023 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910024 HttpRequestInfo request;
10025 HttpRequestInfo push_request;
Ramin Halavatib5e433e2018-02-07 07:41:1010026 request.traffic_annotation =
10027 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910028
[email protected]7c6f7ba2012-04-03 04:09:2910029 request.method = "GET";
bncce36dca22015-04-21 22:11:2310030 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910031 push_request.method = "GET";
10032 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e2018-02-07 07:41:1010033 push_request.traffic_annotation =
10034 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910035
tbansal28e68f82016-02-04 02:56:1510036 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910037 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910038 ProxyResolutionService::CreateFixedFromPacResult(
10039 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110040 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710041 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010042
Eric Roman3d8546a2018-09-10 17:00:5210043 session_deps_.proxy_resolution_service->SetProxyDelegate(
10044 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010045
danakj1fd259a02016-04-16 03:17:0910046 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910047
Ryan Hamilton0239aac2018-05-19 00:03:1310048 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510049 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310050 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510051 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910052
10053 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110054 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510055 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910056 };
10057
Ryan Hamilton0239aac2018-05-19 00:03:1310058 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510059 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610060
Ryan Hamilton0239aac2018-05-19 00:03:1310061 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510062 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910063
Ryan Hamilton0239aac2018-05-19 00:03:1310064 spdy::SpdySerializedFrame stream1_body(
10065 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910066
Ryan Hamilton0239aac2018-05-19 00:03:1310067 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910068 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910069
10070 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610071 CreateMockRead(stream2_syn, 1, ASYNC),
10072 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510073 CreateMockRead(stream1_body, 4, ASYNC),
10074 CreateMockRead(stream2_body, 5, ASYNC),
10075 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910076 };
10077
Ryan Sleevib8d7ea02018-05-07 20:01:0110078 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710079 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910080 // Negotiate SPDY to the proxy
10081 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610082 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710083 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910084
bnc87dcefc2017-05-25 12:47:5810085 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910086 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910087 TestCompletionCallback callback;
10088 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110089 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910090
10091 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110092 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910093 const HttpResponseInfo* response = trans->GetResponseInfo();
10094
bnc87dcefc2017-05-25 12:47:5810095 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910096 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010097 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110098 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910099
10100 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110101 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910102 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10103
wezca1070932016-05-26 20:30:5210104 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910105 EXPECT_TRUE(response->headers->IsKeepAlive());
10106
10107 EXPECT_EQ(200, response->headers->response_code());
10108 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10109
10110 std::string response_data;
10111 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110112 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910113 EXPECT_EQ("hello!", response_data);
10114
[email protected]029c83b62013-01-24 05:28:2010115 LoadTimingInfo load_timing_info;
10116 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10117 TestLoadTimingNotReusedWithPac(load_timing_info,
10118 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10119
[email protected]7c6f7ba2012-04-03 04:09:2910120 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210121 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910122 EXPECT_EQ(200, push_response->headers->response_code());
10123
10124 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110125 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910126 EXPECT_EQ("pushed", response_data);
10127
[email protected]029c83b62013-01-24 05:28:2010128 LoadTimingInfo push_load_timing_info;
10129 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10130 TestLoadTimingReusedWithPac(push_load_timing_info);
10131 // The transactions should share a socket ID, despite being for different
10132 // origins.
10133 EXPECT_EQ(load_timing_info.socket_log_id,
10134 push_load_timing_info.socket_log_id);
10135
[email protected]7c6f7ba2012-04-03 04:09:2910136 trans.reset();
10137 push_trans.reset();
10138 session->CloseAllConnections();
10139}
10140
[email protected]8c843192012-04-05 07:15:0010141// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110142TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510143 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910144 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510145 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10146 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010147 HttpRequestInfo request;
10148
10149 request.method = "GET";
bncce36dca22015-04-21 22:11:2310150 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010151 request.traffic_annotation =
10152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010153
Ramin Halavatica8d5252018-03-12 05:33:4910154 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10155 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110156 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710157 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010158
10159 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210160 session_deps_.proxy_resolution_service->SetProxyDelegate(
10161 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010162
danakj1fd259a02016-04-16 03:17:0910163 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010164
Ryan Hamilton0239aac2018-05-19 00:03:1310165 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510166 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010167
Ryan Hamilton0239aac2018-05-19 00:03:1310168 spdy::SpdySerializedFrame push_rst(
10169 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010170
10171 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110172 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0010173 };
10174
Ryan Hamilton0239aac2018-05-19 00:03:1310175 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510176 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0010177
Ryan Hamilton0239aac2018-05-19 00:03:1310178 spdy::SpdySerializedFrame stream1_body(
10179 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0010180
Ryan Hamilton0239aac2018-05-19 00:03:1310181 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510182 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0010183
10184 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110185 CreateMockRead(stream1_reply, 1, ASYNC),
10186 CreateMockRead(stream2_syn, 2, ASYNC),
10187 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5910188 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0010189 };
10190
Ryan Sleevib8d7ea02018-05-07 20:01:0110191 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710192 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0010193 // Negotiate SPDY to the proxy
10194 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610195 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710196 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0010197
bnc87dcefc2017-05-25 12:47:5810198 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910199 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0010200 TestCompletionCallback callback;
10201 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110202 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0010203
10204 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110205 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010206 const HttpResponseInfo* response = trans->GetResponseInfo();
10207
wezca1070932016-05-26 20:30:5210208 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0010209 EXPECT_TRUE(response->headers->IsKeepAlive());
10210
10211 EXPECT_EQ(200, response->headers->response_code());
10212 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10213
10214 std::string response_data;
10215 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110216 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010217 EXPECT_EQ("hello!", response_data);
10218
10219 trans.reset();
10220 session->CloseAllConnections();
10221}
10222
tbansal8ef1d3e2016-02-03 04:05:4210223// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
10224// resources.
bncd16676a2016-07-20 16:23:0110225TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510226 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910227 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510228 proxy_delegate->set_trusted_spdy_proxy(
10229 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
10230
tbansal8ef1d3e2016-02-03 04:05:4210231 HttpRequestInfo request;
10232
10233 request.method = "GET";
10234 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010235 request.traffic_annotation =
10236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210237
10238 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4910239 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10240 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210241 BoundTestNetLog log;
10242 session_deps_.net_log = log.bound().net_log();
10243
10244 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210245 session_deps_.proxy_resolution_service->SetProxyDelegate(
10246 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4210247
danakj1fd259a02016-04-16 03:17:0910248 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4210249
Ryan Hamilton0239aac2018-05-19 00:03:1310250 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510251 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310252 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510253 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4210254
10255 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110256 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510257 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4210258 };
10259
Ryan Hamilton0239aac2018-05-19 00:03:1310260 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1510261 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210262
Ryan Hamilton0239aac2018-05-19 00:03:1310263 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3310264 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4910265
Ryan Hamilton0239aac2018-05-19 00:03:1310266 spdy::SpdySerializedFrame stream1_body(
10267 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210268
Ryan Hamilton0239aac2018-05-19 00:03:1310269 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1510270 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210271
Ryan Hamilton0239aac2018-05-19 00:03:1310272 spdy::SpdySerializedFrame stream2_body(
10273 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210274
10275 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110276 CreateMockRead(stream1_reply, 1, ASYNC),
10277 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510278 CreateMockRead(stream1_body, 4, ASYNC),
10279 CreateMockRead(stream2_body, 5, ASYNC),
10280 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4210281 };
10282
Ryan Sleevib8d7ea02018-05-07 20:01:0110283 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4210284 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10285 // Negotiate SPDY to the proxy
10286 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610287 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4210288 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
10289
bnc87dcefc2017-05-25 12:47:5810290 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910291 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4210292 TestCompletionCallback callback;
10293 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110294 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4210295
10296 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110297 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210298 const HttpResponseInfo* response = trans->GetResponseInfo();
10299
wezca1070932016-05-26 20:30:5210300 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4210301 EXPECT_TRUE(response->headers->IsKeepAlive());
10302
10303 EXPECT_EQ(200, response->headers->response_code());
10304 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10305
10306 std::string response_data;
10307 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110308 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210309 EXPECT_EQ("hello!", response_data);
10310
10311 trans.reset();
10312 session->CloseAllConnections();
10313}
10314
[email protected]2df19bb2010-08-25 20:13:4610315// Test HTTPS connections to a site with a bad certificate, going through an
10316// HTTPS proxy
bncd16676a2016-07-20 16:23:0110317TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910318 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10319 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610320
10321 HttpRequestInfo request;
10322 request.method = "GET";
bncce36dca22015-04-21 22:11:2310323 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010324 request.traffic_annotation =
10325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610326
10327 // Attempt to fetch the URL from a server with a bad cert
10328 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710329 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10330 "Host: www.example.org:443\r\n"
10331 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610332 };
10333
10334 MockRead bad_cert_reads[] = {
10335 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610336 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4610337 };
10338
10339 // Attempt to fetch the URL with a good cert
10340 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710341 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10342 "Host: www.example.org:443\r\n"
10343 "Proxy-Connection: keep-alive\r\n\r\n"),
10344 MockWrite("GET / HTTP/1.1\r\n"
10345 "Host: www.example.org\r\n"
10346 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610347 };
10348
10349 MockRead good_cert_reads[] = {
10350 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10351 MockRead("HTTP/1.0 200 OK\r\n"),
10352 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10353 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610354 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610355 };
10356
Ryan Sleevib8d7ea02018-05-07 20:01:0110357 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
10358 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0610359 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10360 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4610361
10362 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0710363 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10364 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10365 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4610366
10367 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0710368 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10369 session_deps_.socket_factory->AddSocketDataProvider(&data);
10370 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4610371
[email protected]49639fa2011-12-20 23:22:4110372 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610373
danakj1fd259a02016-04-16 03:17:0910374 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610375 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610376
tfarina42834112016-09-22 13:38:2010377 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110378 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610379
10380 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110381 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4610382
bnc691fda62016-08-12 00:43:1610383 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110384 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610385
10386 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110387 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4610388
bnc691fda62016-08-12 00:43:1610389 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610390
wezca1070932016-05-26 20:30:5210391 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610392 EXPECT_EQ(100, response->headers->GetContentLength());
10393}
10394
bncd16676a2016-07-20 16:23:0110395TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4210396 HttpRequestInfo request;
10397 request.method = "GET";
bncce36dca22015-04-21 22:11:2310398 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310399 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10400 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e2018-02-07 07:41:1010401 request.traffic_annotation =
10402 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210403
danakj1fd259a02016-04-16 03:17:0910404 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610405 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710406
[email protected]1c773ea12009-04-28 19:58:4210407 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310408 MockWrite(
10409 "GET / HTTP/1.1\r\n"
10410 "Host: www.example.org\r\n"
10411 "Connection: keep-alive\r\n"
10412 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210413 };
10414
10415 // Lastly, the server responds with the actual content.
10416 MockRead data_reads[] = {
10417 MockRead("HTTP/1.0 200 OK\r\n"),
10418 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10419 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610420 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210421 };
10422
Ryan Sleevib8d7ea02018-05-07 20:01:0110423 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710424 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210425
[email protected]49639fa2011-12-20 23:22:4110426 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210427
tfarina42834112016-09-22 13:38:2010428 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110429 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210430
10431 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110432 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210433}
10434
bncd16676a2016-07-20 16:23:0110435TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0010436 // Test user agent values, used both for the request header of the original
10437 // request, and the value returned by the HttpUserAgentSettings. nullptr means
10438 // no request header / no HttpUserAgentSettings object.
10439 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2910440
Matt Menked732ea42019-03-08 12:05:0010441 for (const char* setting_user_agent : kTestUserAgents) {
10442 if (!setting_user_agent) {
10443 session_deps_.http_user_agent_settings.reset();
10444 } else {
10445 session_deps_.http_user_agent_settings =
10446 std::make_unique<StaticHttpUserAgentSettings>(
10447 std::string() /* accept-language */, setting_user_agent);
10448 }
10449 session_deps_.proxy_resolution_service =
10450 ProxyResolutionService::CreateFixed("myproxy:70",
10451 TRAFFIC_ANNOTATION_FOR_TESTS);
10452 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10453 for (const char* request_user_agent : kTestUserAgents) {
10454 HttpRequestInfo request;
10455 request.method = "GET";
10456 request.url = GURL("https://www.example.org/");
10457 if (request_user_agent) {
10458 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10459 request_user_agent);
10460 }
10461 request.traffic_annotation =
10462 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710463
Matt Menked732ea42019-03-08 12:05:0010464 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2910465
Matt Menked732ea42019-03-08 12:05:0010466 std::string expected_request;
10467 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
10468 expected_request =
10469 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10470 "Host: www.example.org:443\r\n"
10471 "Proxy-Connection: keep-alive\r\n\r\n";
10472 } else {
10473 expected_request = base::StringPrintf(
10474 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10475 "Host: www.example.org:443\r\n"
10476 "Proxy-Connection: keep-alive\r\n"
10477 "User-Agent: %s\r\n\r\n",
10478 setting_user_agent);
10479 }
10480 MockWrite data_writes[] = {
10481 MockWrite(expected_request.c_str()),
10482 };
10483 MockRead data_reads[] = {
10484 // Return an error, so the transaction stops here (this test isn't
10485 // interested in the rest).
10486 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10487 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10488 MockRead("Proxy-Connection: close\r\n\r\n"),
10489 };
[email protected]da81f132010-08-18 23:39:2910490
Matt Menked732ea42019-03-08 12:05:0010491 StaticSocketDataProvider data(data_reads, data_writes);
10492 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2910493
Matt Menked732ea42019-03-08 12:05:0010494 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2910495
Matt Menked732ea42019-03-08 12:05:0010496 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10497 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10498
10499 rv = callback.WaitForResult();
10500 EXPECT_THAT(rv, IsOk());
10501 }
10502 }
[email protected]da81f132010-08-18 23:39:2910503}
10504
bncd16676a2016-07-20 16:23:0110505TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4210506 HttpRequestInfo request;
10507 request.method = "GET";
bncce36dca22015-04-21 22:11:2310508 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1610509 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
10510 "http://the.previous.site.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1010511 request.traffic_annotation =
10512 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210513
danakj1fd259a02016-04-16 03:17:0910514 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610515 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710516
[email protected]1c773ea12009-04-28 19:58:4210517 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310518 MockWrite(
10519 "GET / HTTP/1.1\r\n"
10520 "Host: www.example.org\r\n"
10521 "Connection: keep-alive\r\n"
10522 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210523 };
10524
10525 // Lastly, the server responds with the actual content.
10526 MockRead data_reads[] = {
10527 MockRead("HTTP/1.0 200 OK\r\n"),
10528 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10529 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610530 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210531 };
10532
Ryan Sleevib8d7ea02018-05-07 20:01:0110533 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710534 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210535
[email protected]49639fa2011-12-20 23:22:4110536 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210537
tfarina42834112016-09-22 13:38:2010538 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110539 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210540
10541 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110542 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210543}
10544
bncd16676a2016-07-20 16:23:0110545TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210546 HttpRequestInfo request;
10547 request.method = "POST";
bncce36dca22015-04-21 22:11:2310548 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010549 request.traffic_annotation =
10550 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210551
danakj1fd259a02016-04-16 03:17:0910552 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610553 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710554
[email protected]1c773ea12009-04-28 19:58:4210555 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310556 MockWrite(
10557 "POST / HTTP/1.1\r\n"
10558 "Host: www.example.org\r\n"
10559 "Connection: keep-alive\r\n"
10560 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210561 };
10562
10563 // Lastly, the server responds with the actual content.
10564 MockRead data_reads[] = {
10565 MockRead("HTTP/1.0 200 OK\r\n"),
10566 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10567 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610568 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210569 };
10570
Ryan Sleevib8d7ea02018-05-07 20:01:0110571 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710572 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210573
[email protected]49639fa2011-12-20 23:22:4110574 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210575
tfarina42834112016-09-22 13:38:2010576 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110577 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210578
10579 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110580 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210581}
10582
bncd16676a2016-07-20 16:23:0110583TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210584 HttpRequestInfo request;
10585 request.method = "PUT";
bncce36dca22015-04-21 22:11:2310586 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010587 request.traffic_annotation =
10588 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210589
danakj1fd259a02016-04-16 03:17:0910590 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610591 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710592
[email protected]1c773ea12009-04-28 19:58:4210593 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310594 MockWrite(
10595 "PUT / HTTP/1.1\r\n"
10596 "Host: www.example.org\r\n"
10597 "Connection: keep-alive\r\n"
10598 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210599 };
10600
10601 // Lastly, the server responds with the actual content.
10602 MockRead data_reads[] = {
10603 MockRead("HTTP/1.0 200 OK\r\n"),
10604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10605 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610606 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210607 };
10608
Ryan Sleevib8d7ea02018-05-07 20:01:0110609 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710610 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210611
[email protected]49639fa2011-12-20 23:22:4110612 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210613
tfarina42834112016-09-22 13:38:2010614 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110615 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210616
10617 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110618 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210619}
10620
bncd16676a2016-07-20 16:23:0110621TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210622 HttpRequestInfo request;
10623 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2310624 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010625 request.traffic_annotation =
10626 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210627
danakj1fd259a02016-04-16 03:17:0910628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610629 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710630
[email protected]1c773ea12009-04-28 19:58:4210631 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1310632 MockWrite("HEAD / HTTP/1.1\r\n"
10633 "Host: www.example.org\r\n"
10634 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210635 };
10636
10637 // Lastly, the server responds with the actual content.
10638 MockRead data_reads[] = {
10639 MockRead("HTTP/1.0 200 OK\r\n"),
10640 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10641 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610642 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210643 };
10644
Ryan Sleevib8d7ea02018-05-07 20:01:0110645 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710646 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210647
[email protected]49639fa2011-12-20 23:22:4110648 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210649
tfarina42834112016-09-22 13:38:2010650 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110651 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210652
10653 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110654 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210655}
10656
bncd16676a2016-07-20 16:23:0110657TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4210658 HttpRequestInfo request;
10659 request.method = "GET";
bncce36dca22015-04-21 22:11:2310660 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210661 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1010662 request.traffic_annotation =
10663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210664
danakj1fd259a02016-04-16 03:17:0910665 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610666 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710667
[email protected]1c773ea12009-04-28 19:58:4210668 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310669 MockWrite(
10670 "GET / HTTP/1.1\r\n"
10671 "Host: www.example.org\r\n"
10672 "Connection: keep-alive\r\n"
10673 "Pragma: no-cache\r\n"
10674 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210675 };
10676
10677 // Lastly, the server responds with the actual content.
10678 MockRead data_reads[] = {
10679 MockRead("HTTP/1.0 200 OK\r\n"),
10680 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10681 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610682 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210683 };
10684
Ryan Sleevib8d7ea02018-05-07 20:01:0110685 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710686 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210687
[email protected]49639fa2011-12-20 23:22:4110688 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210689
tfarina42834112016-09-22 13:38:2010690 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110691 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210692
10693 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110694 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210695}
10696
bncd16676a2016-07-20 16:23:0110697TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4210698 HttpRequestInfo request;
10699 request.method = "GET";
bncce36dca22015-04-21 22:11:2310700 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210701 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e2018-02-07 07:41:1010702 request.traffic_annotation =
10703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210704
danakj1fd259a02016-04-16 03:17:0910705 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610706 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710707
[email protected]1c773ea12009-04-28 19:58:4210708 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310709 MockWrite(
10710 "GET / HTTP/1.1\r\n"
10711 "Host: www.example.org\r\n"
10712 "Connection: keep-alive\r\n"
10713 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210714 };
10715
10716 // Lastly, the server responds with the actual content.
10717 MockRead data_reads[] = {
10718 MockRead("HTTP/1.0 200 OK\r\n"),
10719 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10720 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610721 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210722 };
10723
Ryan Sleevib8d7ea02018-05-07 20:01:0110724 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710725 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210726
[email protected]49639fa2011-12-20 23:22:4110727 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210728
tfarina42834112016-09-22 13:38:2010729 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110730 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210731
10732 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110733 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210734}
10735
bncd16676a2016-07-20 16:23:0110736TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4210737 HttpRequestInfo request;
10738 request.method = "GET";
bncce36dca22015-04-21 22:11:2310739 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310740 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e2018-02-07 07:41:1010741 request.traffic_annotation =
10742 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210743
danakj1fd259a02016-04-16 03:17:0910744 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610745 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710746
[email protected]1c773ea12009-04-28 19:58:4210747 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310748 MockWrite(
10749 "GET / HTTP/1.1\r\n"
10750 "Host: www.example.org\r\n"
10751 "Connection: keep-alive\r\n"
10752 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210753 };
10754
10755 // Lastly, the server responds with the actual content.
10756 MockRead data_reads[] = {
10757 MockRead("HTTP/1.0 200 OK\r\n"),
10758 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10759 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610760 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210761 };
10762
Ryan Sleevib8d7ea02018-05-07 20:01:0110763 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710764 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210765
[email protected]49639fa2011-12-20 23:22:4110766 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210767
tfarina42834112016-09-22 13:38:2010768 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110769 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210770
10771 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110772 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210773}
10774
bncd16676a2016-07-20 16:23:0110775TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4710776 HttpRequestInfo request;
10777 request.method = "GET";
bncce36dca22015-04-21 22:11:2310778 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310779 request.extra_headers.SetHeader("referer", "www.foo.com");
10780 request.extra_headers.SetHeader("hEllo", "Kitty");
10781 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e2018-02-07 07:41:1010782 request.traffic_annotation =
10783 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4710784
danakj1fd259a02016-04-16 03:17:0910785 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610786 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710787
[email protected]270c6412010-03-29 22:02:4710788 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310789 MockWrite(
10790 "GET / HTTP/1.1\r\n"
10791 "Host: www.example.org\r\n"
10792 "Connection: keep-alive\r\n"
10793 "referer: www.foo.com\r\n"
10794 "hEllo: Kitty\r\n"
10795 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4710796 };
10797
10798 // Lastly, the server responds with the actual content.
10799 MockRead data_reads[] = {
10800 MockRead("HTTP/1.0 200 OK\r\n"),
10801 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10802 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610803 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4710804 };
10805
Ryan Sleevib8d7ea02018-05-07 20:01:0110806 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710807 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4710808
[email protected]49639fa2011-12-20 23:22:4110809 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4710810
tfarina42834112016-09-22 13:38:2010811 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110812 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4710813
10814 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110815 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4710816}
10817
bncd16676a2016-07-20 16:23:0110818TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710819 HttpRequestInfo request;
10820 request.method = "GET";
bncce36dca22015-04-21 22:11:2310821 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010822 request.traffic_annotation =
10823 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710824
Lily Houghton8c2f97d2018-01-22 05:06:5910825 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910826 ProxyResolutionService::CreateFixedFromPacResult(
10827 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110828 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710829 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210830
danakj1fd259a02016-04-16 03:17:0910831 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610832 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210833
[email protected]3cd17242009-06-23 02:59:0210834 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10835 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10836
10837 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410838 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10839 MockWrite("GET / HTTP/1.1\r\n"
10840 "Host: www.example.org\r\n"
10841 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210842
10843 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410844 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10845 MockRead("HTTP/1.0 200 OK\r\n"),
10846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10847 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0210848
Ryan Sleevib8d7ea02018-05-07 20:01:0110849 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710850 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0210851
[email protected]49639fa2011-12-20 23:22:4110852 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0210853
tfarina42834112016-09-22 13:38:2010854 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110855 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0210856
10857 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110858 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210859
bnc691fda62016-08-12 00:43:1610860 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210861 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0210862
tbansal2ecbbc72016-10-06 17:15:4710863 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2010864 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610865 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010866 TestLoadTimingNotReusedWithPac(load_timing_info,
10867 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10868
[email protected]3cd17242009-06-23 02:59:0210869 std::string response_text;
bnc691fda62016-08-12 00:43:1610870 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110871 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210872 EXPECT_EQ("Payload", response_text);
10873}
10874
bncd16676a2016-07-20 16:23:0110875TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710876 HttpRequestInfo request;
10877 request.method = "GET";
bncce36dca22015-04-21 22:11:2310878 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010879 request.traffic_annotation =
10880 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710881
Lily Houghton8c2f97d2018-01-22 05:06:5910882 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910883 ProxyResolutionService::CreateFixedFromPacResult(
10884 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110885 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710886 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210887
danakj1fd259a02016-04-16 03:17:0910888 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610889 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210890
[email protected]3cd17242009-06-23 02:59:0210891 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
10892 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10893
10894 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310895 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2410896 base::size(write_buffer)),
10897 MockWrite("GET / HTTP/1.1\r\n"
10898 "Host: www.example.org\r\n"
10899 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210900
10901 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410902 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
10903 base::size(read_buffer)),
10904 MockRead("HTTP/1.0 200 OK\r\n"),
10905 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10906 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3510907
Ryan Sleevib8d7ea02018-05-07 20:01:0110908 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710909 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3510910
[email protected]8ddf8322012-02-23 18:08:0610911 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3510913
[email protected]49639fa2011-12-20 23:22:4110914 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3510915
tfarina42834112016-09-22 13:38:2010916 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110917 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3510918
10919 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110920 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510921
[email protected]029c83b62013-01-24 05:28:2010922 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610923 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010924 TestLoadTimingNotReusedWithPac(load_timing_info,
10925 CONNECT_TIMING_HAS_SSL_TIMES);
10926
bnc691fda62016-08-12 00:43:1610927 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210928 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4710929 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3510930
10931 std::string response_text;
bnc691fda62016-08-12 00:43:1610932 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110933 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510934 EXPECT_EQ("Payload", response_text);
10935}
10936
bncd16676a2016-07-20 16:23:0110937TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2010938 HttpRequestInfo request;
10939 request.method = "GET";
bncce36dca22015-04-21 22:11:2310940 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010941 request.traffic_annotation =
10942 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2010943
Ramin Halavatica8d5252018-03-12 05:33:4910944 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10945 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110946 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710947 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2010948
danakj1fd259a02016-04-16 03:17:0910949 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610950 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2010951
10952 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10953 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10954
10955 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410956 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10957 MockWrite("GET / HTTP/1.1\r\n"
10958 "Host: www.example.org\r\n"
10959 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2010960
10961 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410962 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10963 MockRead("HTTP/1.0 200 OK\r\n"),
10964 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10965 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2010966
Ryan Sleevib8d7ea02018-05-07 20:01:0110967 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710968 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2010969
10970 TestCompletionCallback callback;
10971
tfarina42834112016-09-22 13:38:2010972 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110973 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2010974
10975 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110976 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010977
bnc691fda62016-08-12 00:43:1610978 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210979 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2010980
10981 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610982 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010983 TestLoadTimingNotReused(load_timing_info,
10984 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10985
10986 std::string response_text;
bnc691fda62016-08-12 00:43:1610987 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110988 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010989 EXPECT_EQ("Payload", response_text);
10990}
10991
bncd16676a2016-07-20 16:23:0110992TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710993 HttpRequestInfo request;
10994 request.method = "GET";
bncce36dca22015-04-21 22:11:2310995 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1010996 request.traffic_annotation =
10997 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710998
Lily Houghton8c2f97d2018-01-22 05:06:5910999 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911000 ProxyResolutionService::CreateFixedFromPacResult(
11001 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111002 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711003 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511004
danakj1fd259a02016-04-16 03:17:0911005 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611006 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511007
[email protected]e0c27be2009-07-15 13:09:3511008 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11009 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711010 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311011 0x05, // Version
11012 0x01, // Command (CONNECT)
11013 0x00, // Reserved.
11014 0x03, // Address type (DOMAINNAME).
11015 0x0F, // Length of domain (15)
11016 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11017 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711018 };
[email protected]e0c27be2009-07-15 13:09:3511019 const char kSOCKS5OkResponse[] =
11020 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11021
11022 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411023 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11024 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11025 MockWrite("GET / HTTP/1.1\r\n"
11026 "Host: www.example.org\r\n"
11027 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511028
11029 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411030 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11031 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11032 MockRead("HTTP/1.0 200 OK\r\n"),
11033 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11034 MockRead("Payload"),
11035 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511036
Ryan Sleevib8d7ea02018-05-07 20:01:0111037 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711038 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511039
[email protected]49639fa2011-12-20 23:22:4111040 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511041
tfarina42834112016-09-22 13:38:2011042 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111043 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511044
11045 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111046 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511047
bnc691fda62016-08-12 00:43:1611048 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211049 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711050 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511051
[email protected]029c83b62013-01-24 05:28:2011052 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611053 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011054 TestLoadTimingNotReusedWithPac(load_timing_info,
11055 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11056
[email protected]e0c27be2009-07-15 13:09:3511057 std::string response_text;
bnc691fda62016-08-12 00:43:1611058 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111059 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511060 EXPECT_EQ("Payload", response_text);
11061}
11062
bncd16676a2016-07-20 16:23:0111063TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711064 HttpRequestInfo request;
11065 request.method = "GET";
bncce36dca22015-04-21 22:11:2311066 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011067 request.traffic_annotation =
11068 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711069
Lily Houghton8c2f97d2018-01-22 05:06:5911070 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911071 ProxyResolutionService::CreateFixedFromPacResult(
11072 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111073 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711074 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511075
danakj1fd259a02016-04-16 03:17:0911076 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611077 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511078
[email protected]e0c27be2009-07-15 13:09:3511079 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11080 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711081 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311082 0x05, // Version
11083 0x01, // Command (CONNECT)
11084 0x00, // Reserved.
11085 0x03, // Address type (DOMAINNAME).
11086 0x0F, // Length of domain (15)
11087 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11088 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711089 };
11090
[email protected]e0c27be2009-07-15 13:09:3511091 const char kSOCKS5OkResponse[] =
11092 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11093
11094 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411095 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311096 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411097 base::size(kSOCKS5OkRequest)),
11098 MockWrite("GET / HTTP/1.1\r\n"
11099 "Host: www.example.org\r\n"
11100 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511101
11102 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411103 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11104 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11105 MockRead("HTTP/1.0 200 OK\r\n"),
11106 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11107 MockRead("Payload"),
11108 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211109
Ryan Sleevib8d7ea02018-05-07 20:01:0111110 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711111 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211112
[email protected]8ddf8322012-02-23 18:08:0611113 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711114 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211115
[email protected]49639fa2011-12-20 23:22:4111116 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211117
tfarina42834112016-09-22 13:38:2011118 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111119 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211120
11121 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111122 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211123
bnc691fda62016-08-12 00:43:1611124 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211125 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711126 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211127
[email protected]029c83b62013-01-24 05:28:2011128 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 TestLoadTimingNotReusedWithPac(load_timing_info,
11131 CONNECT_TIMING_HAS_SSL_TIMES);
11132
[email protected]3cd17242009-06-23 02:59:0211133 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]3cd17242009-06-23 02:59:0211136 EXPECT_EQ("Payload", response_text);
11137}
11138
[email protected]448d4ca52012-03-04 04:12:2311139namespace {
11140
Matt Menkef6edce752019-03-19 17:21:5611141// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611142
Matt Menkef6edce752019-03-19 17:21:5611143struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611144 std::string proxy_server;
11145 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611146 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811147 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611148};
11149
Matt Menkef6edce752019-03-19 17:21:5611150std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711151 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911152 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611153
bnc525e175a2016-06-20 12:36:4011154 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311155 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111156 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211157 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111158 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211159 url::SchemeHostPort("https", "host.with.alternate", 443),
zhongyi3d4a55e72016-04-22 20:36:4611160 alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611161
11162 return session;
11163}
11164
Matt Menkef6edce752019-03-19 17:21:5611165int GroupIdTransactionHelper(const std::string& url,
11166 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611167 HttpRequestInfo request;
11168 request.method = "GET";
11169 request.url = GURL(url);
Ramin Halavatib5e433e2018-02-07 07:41:1011170 request.traffic_annotation =
11171 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611172
bnc691fda62016-08-12 00:43:1611173 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2711174
[email protected]49639fa2011-12-20 23:22:4111175 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0611176
11177 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2011178 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0611179}
11180
[email protected]448d4ca52012-03-04 04:12:2311181} // namespace
11182
Matt Menkef6edce752019-03-19 17:21:5611183TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
11184 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311185 {
Matt Menkef6edce752019-03-19 17:21:5611186 "", // unused
11187 "http://www.example.org/direct",
11188 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11189 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911190 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611191 false,
bncce36dca22015-04-21 22:11:2311192 },
11193 {
Matt Menkef6edce752019-03-19 17:21:5611194 "", // unused
11195 "http://[2001:1418:13:1::25]/direct",
11196 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
11197 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911198 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611199 false,
bncce36dca22015-04-21 22:11:2311200 },
[email protected]04e5be32009-06-26 20:00:3111201
bncce36dca22015-04-21 22:11:2311202 // SSL Tests
11203 {
Matt Menkef6edce752019-03-19 17:21:5611204 "", // unused
11205 "https://www.example.org/direct_ssl",
11206 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11207 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911208 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611209 true,
bncce36dca22015-04-21 22:11:2311210 },
11211 {
Matt Menkef6edce752019-03-19 17:21:5611212 "", // unused
11213 "https://[2001:1418:13:1::25]/direct",
11214 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
11215 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911216 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611217 true,
bncce36dca22015-04-21 22:11:2311218 },
11219 {
Matt Menkef6edce752019-03-19 17:21:5611220 "", // unused
11221 "https://host.with.alternate/direct",
11222 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11223 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911224 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611225 true,
bncce36dca22015-04-21 22:11:2311226 },
[email protected]2d731a32010-04-29 01:04:0611227 };
[email protected]2ff8b312010-04-26 22:20:5411228
Avi Drissman4365a4782018-12-28 19:26:2411229 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911230 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911231 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11232 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911233 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611234 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611235
mmenkee65e7af2015-10-13 17:16:4211236 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5611237 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611238 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911239 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011240 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
11241 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4811242 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611243
11244 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611245 GroupIdTransactionHelper(tests[i].url, session.get()));
11246 EXPECT_EQ(tests[i].expected_group_id,
11247 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2311248 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0611249 }
[email protected]2d731a32010-04-29 01:04:0611250}
11251
Matt Menkef6edce752019-03-19 17:21:5611252TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
11253 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311254 {
Matt Menke4802de62019-03-08 22:47:5011255 "http_proxy",
11256 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611257 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11258 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911259 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011260 false,
bncce36dca22015-04-21 22:11:2311261 },
[email protected]2d731a32010-04-29 01:04:0611262
bncce36dca22015-04-21 22:11:2311263 // SSL Tests
11264 {
Matt Menke4802de62019-03-08 22:47:5011265 "http_proxy",
11266 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5611267 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11268 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911269 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011270 true,
bncce36dca22015-04-21 22:11:2311271 },
[email protected]af3490e2010-10-16 21:02:2911272
bncce36dca22015-04-21 22:11:2311273 {
Matt Menke4802de62019-03-08 22:47:5011274 "http_proxy",
11275 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611276 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11277 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911278 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011279 true,
bncce36dca22015-04-21 22:11:2311280 },
[email protected]45499252013-01-23 17:12:5611281
bncce36dca22015-04-21 22:11:2311282 {
Matt Menke4802de62019-03-08 22:47:5011283 "http_proxy",
11284 "ftp://ftp.google.com/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611285 ClientSocketPool::GroupId(HostPortPair("ftp.google.com", 21),
11286 ClientSocketPool::SocketType::kFtp,
Matt Menkebdf777802019-04-22 19:38:5911287 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011288 false,
bncce36dca22015-04-21 22:11:2311289 },
[email protected]2d731a32010-04-29 01:04:0611290 };
11291
Avi Drissman4365a4782018-12-28 19:26:2411292 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911293 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911294 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11295 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911296 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611297 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611298
mmenkee65e7af2015-10-13 17:16:4211299 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0611300
Matt Menkee8648fa2019-01-17 16:47:0711301 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
11302 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5611303 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3611304 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911305 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011306 mock_pool_manager->SetSocketPool(proxy_server,
11307 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4811308 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611309
11310 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611311 GroupIdTransactionHelper(tests[i].url, session.get()));
11312 EXPECT_EQ(tests[i].expected_group_id,
11313 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0611314 }
[email protected]2d731a32010-04-29 01:04:0611315}
11316
Matt Menkef6edce752019-03-19 17:21:5611317TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
11318 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311319 {
Matt Menke4802de62019-03-08 22:47:5011320 "socks4://socks_proxy:1080",
11321 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5611322 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11323 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911324 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011325 false,
bncce36dca22015-04-21 22:11:2311326 },
11327 {
Matt Menke4802de62019-03-08 22:47:5011328 "socks5://socks_proxy:1080",
11329 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5611330 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11331 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911332 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011333 false,
bncce36dca22015-04-21 22:11:2311334 },
[email protected]2d731a32010-04-29 01:04:0611335
bncce36dca22015-04-21 22:11:2311336 // SSL Tests
11337 {
Matt Menke4802de62019-03-08 22:47:5011338 "socks4://socks_proxy:1080",
11339 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5611340 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11341 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911342 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011343 true,
bncce36dca22015-04-21 22:11:2311344 },
11345 {
Matt Menke4802de62019-03-08 22:47:5011346 "socks5://socks_proxy:1080",
11347 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5611348 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11349 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911350 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011351 true,
bncce36dca22015-04-21 22:11:2311352 },
[email protected]af3490e2010-10-16 21:02:2911353
bncce36dca22015-04-21 22:11:2311354 {
Matt Menke4802de62019-03-08 22:47:5011355 "socks4://socks_proxy:1080",
11356 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611357 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11358 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911359 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011360 true,
bncce36dca22015-04-21 22:11:2311361 },
[email protected]04e5be32009-06-26 20:00:3111362 };
11363
Avi Drissman4365a4782018-12-28 19:26:2411364 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911365 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911366 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11367 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911368 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611369 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0211370
mmenkee65e7af2015-10-13 17:16:4211371 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3111372
Matt Menkee8648fa2019-01-17 16:47:0711373 ProxyServer proxy_server(
11374 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
11375 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5611376 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611377 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911378 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011379 mock_pool_manager->SetSocketPool(proxy_server,
11380 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4811381 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3111382
bnc691fda62016-08-12 00:43:1611383 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3111384
[email protected]2d731a32010-04-29 01:04:0611385 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611386 GroupIdTransactionHelper(tests[i].url, session.get()));
11387 EXPECT_EQ(tests[i].expected_group_id,
11388 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3111389 }
11390}
11391
bncd16676a2016-07-20 16:23:0111392TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2711393 HttpRequestInfo request;
11394 request.method = "GET";
bncce36dca22015-04-21 22:11:2311395 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011396 request.traffic_annotation =
11397 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711398
Ramin Halavatica8d5252018-03-12 05:33:4911399 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11400 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3211401
[email protected]69719062010-01-05 20:09:2111402 // This simulates failure resolving all hostnames; that means we will fail
11403 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0711404 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3211405
danakj1fd259a02016-04-16 03:17:0911406 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611407 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2511408
[email protected]49639fa2011-12-20 23:22:4111409 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2511410
tfarina42834112016-09-22 13:38:2011411 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111412 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2511413
[email protected]9172a982009-06-06 00:30:2511414 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111415 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2511416}
11417
[email protected]0877e3d2009-10-17 22:29:5711418// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0111419TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5711420 HttpRequestInfo request;
11421 request.method = "GET";
11422 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011423 request.traffic_annotation =
11424 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711425
11426 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0611427 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711428 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111429 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0711430 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911431 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711432
[email protected]49639fa2011-12-20 23:22:4111433 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711434
bnc691fda62016-08-12 00:43:1611435 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711436
tfarina42834112016-09-22 13:38:2011437 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111438 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711439
11440 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111441 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5911442
11443 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611444 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911445 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711446}
11447
zmo9528c9f42015-08-04 22:12:0811448// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0111449TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5711450 HttpRequestInfo request;
11451 request.method = "GET";
11452 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1011453 request.traffic_annotation =
11454 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711455
11456 MockRead data_reads[] = {
11457 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0611458 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711459 };
11460
Ryan Sleevib8d7ea02018-05-07 20:01:0111461 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711462 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911463 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711464
[email protected]49639fa2011-12-20 23:22:4111465 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711466
bnc691fda62016-08-12 00:43:1611467 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711468
tfarina42834112016-09-22 13:38:2011469 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711471
11472 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111473 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811474
bnc691fda62016-08-12 00:43:1611475 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211476 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0811477
wezca1070932016-05-26 20:30:5211478 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0811479 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11480
11481 std::string response_data;
bnc691fda62016-08-12 00:43:1611482 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111483 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811484 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5911485
11486 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611487 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911488 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711489}
11490
11491// Make sure that a dropped connection while draining the body for auth
11492// restart does the right thing.
bncd16676a2016-07-20 16:23:0111493TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5711494 HttpRequestInfo request;
11495 request.method = "GET";
bncce36dca22015-04-21 22:11:2311496 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011497 request.traffic_annotation =
11498 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711499
11500 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311501 MockWrite(
11502 "GET / HTTP/1.1\r\n"
11503 "Host: www.example.org\r\n"
11504 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711505 };
11506
11507 MockRead data_reads1[] = {
11508 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
11509 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11510 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11511 MockRead("Content-Length: 14\r\n\r\n"),
11512 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0611513 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711514 };
11515
Ryan Sleevib8d7ea02018-05-07 20:01:0111516 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0711517 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5711518
bnc691fda62016-08-12 00:43:1611519 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5711520 // be issuing -- the final header line contains the credentials.
11521 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311522 MockWrite(
11523 "GET / HTTP/1.1\r\n"
11524 "Host: www.example.org\r\n"
11525 "Connection: keep-alive\r\n"
11526 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711527 };
11528
11529 // Lastly, the server responds with the actual content.
11530 MockRead data_reads2[] = {
11531 MockRead("HTTP/1.1 200 OK\r\n"),
11532 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11533 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611534 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711535 };
11536
Ryan Sleevib8d7ea02018-05-07 20:01:0111537 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0711538 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0911539 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711540
[email protected]49639fa2011-12-20 23:22:4111541 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5711542
bnc691fda62016-08-12 00:43:1611543 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011544
tfarina42834112016-09-22 13:38:2011545 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111546 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711547
11548 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111549 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711550
bnc691fda62016-08-12 00:43:1611551 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211552 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811553 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5711554
[email protected]49639fa2011-12-20 23:22:4111555 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5711556
bnc691fda62016-08-12 00:43:1611557 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0111558 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711559
11560 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111561 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711562
bnc691fda62016-08-12 00:43:1611563 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211564 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811565 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5711566 EXPECT_EQ(100, response->headers->GetContentLength());
11567}
11568
11569// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0111570TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4911571 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11572 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711573
11574 HttpRequestInfo request;
11575 request.method = "GET";
bncce36dca22015-04-21 22:11:2311576 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011577 request.traffic_annotation =
11578 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711579
11580 MockRead proxy_reads[] = {
11581 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0611582 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5711583 };
11584
Ryan Sleevib8d7ea02018-05-07 20:01:0111585 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0611586 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5711587
[email protected]bb88e1d32013-05-03 23:11:0711588 session_deps_.socket_factory->AddSocketDataProvider(&data);
11589 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5711590
[email protected]49639fa2011-12-20 23:22:4111591 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711592
[email protected]bb88e1d32013-05-03 23:11:0711593 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5711594
danakj1fd259a02016-04-16 03:17:0911595 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611596 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711597
tfarina42834112016-09-22 13:38:2011598 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111599 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711600
11601 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111602 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5711603}
11604
bncd16676a2016-07-20 16:23:0111605TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4611606 HttpRequestInfo request;
11607 request.method = "GET";
bncce36dca22015-04-21 22:11:2311608 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011609 request.traffic_annotation =
11610 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4611611
danakj1fd259a02016-04-16 03:17:0911612 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611613 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711614
[email protected]e22e1362009-11-23 21:31:1211615 MockRead data_reads[] = {
11616 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611617 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1211618 };
[email protected]9492e4a2010-02-24 00:58:4611619
Ryan Sleevib8d7ea02018-05-07 20:01:0111620 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711621 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4611622
[email protected]49639fa2011-12-20 23:22:4111623 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4611624
tfarina42834112016-09-22 13:38:2011625 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111626 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4611627
robpercival214763f2016-07-01 23:27:0111628 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4611629
bnc691fda62016-08-12 00:43:1611630 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211631 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4611632
wezca1070932016-05-26 20:30:5211633 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4611634 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11635
11636 std::string response_data;
bnc691fda62016-08-12 00:43:1611637 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111638 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1211639}
11640
bncd16676a2016-07-20 16:23:0111641TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1511642 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5211643 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1411644 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2111645 UploadFileElementReader::ScopedOverridingContentLengthForTests
11646 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3311647
danakj1fd259a02016-04-16 03:17:0911648 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911649 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411650 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0711651 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211652 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711653
11654 HttpRequestInfo request;
11655 request.method = "POST";
bncce36dca22015-04-21 22:11:2311656 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711657 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1011658 request.traffic_annotation =
11659 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711660
danakj1fd259a02016-04-16 03:17:0911661 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611662 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3311663
11664 MockRead data_reads[] = {
11665 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11666 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0611667 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3311668 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111669 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711670 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3311671
[email protected]49639fa2011-12-20 23:22:4111672 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3311673
tfarina42834112016-09-22 13:38:2011674 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111675 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3311676
11677 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111678 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3311679
bnc691fda62016-08-12 00:43:1611680 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211681 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3311682
maksim.sisove869bf52016-06-23 17:11:5211683 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3311684
[email protected]dd3aa792013-07-16 19:10:2311685 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3311686}
11687
bncd16676a2016-07-20 16:23:0111688TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1511689 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5211690 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3611691 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4811692 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
11693 base::WriteFile(temp_file, temp_file_content.c_str(),
11694 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1111695 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3611696
danakj1fd259a02016-04-16 03:17:0911697 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911698 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411699 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0711700 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211701 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711702
11703 HttpRequestInfo request;
11704 request.method = "POST";
bncce36dca22015-04-21 22:11:2311705 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711706 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1011707 request.traffic_annotation =
11708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711709
[email protected]999dd8c2013-11-12 06:45:5411710 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0911711 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611712 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3611713
Ryan Sleevib8d7ea02018-05-07 20:01:0111714 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0711715 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3611716
[email protected]49639fa2011-12-20 23:22:4111717 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3611718
tfarina42834112016-09-22 13:38:2011719 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111720 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3611721
11722 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111723 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3611724
[email protected]dd3aa792013-07-16 19:10:2311725 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3611726}
11727
bncd16676a2016-07-20 16:23:0111728TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0311729 class FakeUploadElementReader : public UploadElementReader {
11730 public:
Chris Watkins7a41d3552017-12-01 02:13:2711731 FakeUploadElementReader() = default;
11732 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0311733
Matt Menkecc1d3a902018-02-05 18:27:3311734 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0311735
11736 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3311737 int Init(CompletionOnceCallback callback) override {
11738 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0311739 return ERR_IO_PENDING;
11740 }
avibf0746c2015-12-09 19:53:1411741 uint64_t GetContentLength() const override { return 0; }
11742 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2011743 int Read(IOBuffer* buf,
11744 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3311745 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0311746 return ERR_FAILED;
11747 }
11748
11749 private:
Matt Menkecc1d3a902018-02-05 18:27:3311750 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0311751 };
11752
11753 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0911754 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11755 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2211756 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0311757
11758 HttpRequestInfo request;
11759 request.method = "POST";
bncce36dca22015-04-21 22:11:2311760 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0311761 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1011762 request.traffic_annotation =
11763 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0311764
danakj1fd259a02016-04-16 03:17:0911765 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5811766 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911767 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0311768
11769 StaticSocketDataProvider data;
11770 session_deps_.socket_factory->AddSocketDataProvider(&data);
11771
11772 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2011773 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111774 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5511775 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0311776
11777 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3311778 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
11779 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0311780
11781 // Return Init()'s result after the transaction gets destroyed.
11782 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3311783 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0311784}
11785
[email protected]aeefc9e82010-02-19 16:18:2711786// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0111787TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2711788 HttpRequestInfo request;
11789 request.method = "GET";
bncce36dca22015-04-21 22:11:2311790 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011791 request.traffic_annotation =
11792 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2711793
11794 // First transaction will request a resource and receive a Basic challenge
11795 // with realm="first_realm".
11796 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311797 MockWrite(
11798 "GET / HTTP/1.1\r\n"
11799 "Host: www.example.org\r\n"
11800 "Connection: keep-alive\r\n"
11801 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711802 };
11803 MockRead data_reads1[] = {
11804 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11805 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11806 "\r\n"),
11807 };
11808
bnc691fda62016-08-12 00:43:1611809 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2711810 // for first_realm. The server will reject and provide a challenge with
11811 // second_realm.
11812 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311813 MockWrite(
11814 "GET / HTTP/1.1\r\n"
11815 "Host: www.example.org\r\n"
11816 "Connection: keep-alive\r\n"
11817 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
11818 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711819 };
11820 MockRead data_reads2[] = {
11821 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11822 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
11823 "\r\n"),
11824 };
11825
11826 // This again fails, and goes back to first_realm. Make sure that the
11827 // entry is removed from cache.
11828 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2311829 MockWrite(
11830 "GET / HTTP/1.1\r\n"
11831 "Host: www.example.org\r\n"
11832 "Connection: keep-alive\r\n"
11833 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
11834 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711835 };
11836 MockRead data_reads3[] = {
11837 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11838 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11839 "\r\n"),
11840 };
11841
11842 // Try one last time (with the correct password) and get the resource.
11843 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2311844 MockWrite(
11845 "GET / HTTP/1.1\r\n"
11846 "Host: www.example.org\r\n"
11847 "Connection: keep-alive\r\n"
11848 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
11849 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711850 };
11851 MockRead data_reads4[] = {
11852 MockRead("HTTP/1.1 200 OK\r\n"
11853 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5011854 "Content-Length: 5\r\n"
11855 "\r\n"
11856 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2711857 };
11858
Ryan Sleevib8d7ea02018-05-07 20:01:0111859 StaticSocketDataProvider data1(data_reads1, data_writes1);
11860 StaticSocketDataProvider data2(data_reads2, data_writes2);
11861 StaticSocketDataProvider data3(data_reads3, data_writes3);
11862 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0711863 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11864 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11865 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11866 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2711867
[email protected]49639fa2011-12-20 23:22:4111868 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2711869
danakj1fd259a02016-04-16 03:17:0911870 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611871 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011872
[email protected]aeefc9e82010-02-19 16:18:2711873 // Issue the first request with Authorize headers. There should be a
11874 // password prompt for first_realm waiting to be filled in after the
11875 // transaction completes.
tfarina42834112016-09-22 13:38:2011876 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711878 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111879 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611880 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211881 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811882 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211883 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411884 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311885 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411886 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911887 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711888
11889 // Issue the second request with an incorrect password. There should be a
11890 // password prompt for second_realm waiting to be filled in after the
11891 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4111892 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1611893 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
11894 callback2.callback());
robpercival214763f2016-07-01 23:27:0111895 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711896 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111897 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611898 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211899 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811900 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211901 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411902 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311903 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411904 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911905 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711906
11907 // Issue the third request with another incorrect password. There should be
11908 // a password prompt for first_realm waiting to be filled in. If the password
11909 // prompt is not present, it indicates that the HttpAuthCacheEntry for
11910 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4111911 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1611912 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
11913 callback3.callback());
robpercival214763f2016-07-01 23:27:0111914 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711915 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0111916 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611917 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211918 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811919 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211920 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411921 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311922 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411923 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911924 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711925
11926 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4111927 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1611928 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
11929 callback4.callback());
robpercival214763f2016-07-01 23:27:0111930 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711931 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0111932 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611933 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211934 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811935 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2711936}
11937
Bence Béky230ac612017-08-30 19:17:0811938// Regression test for https://crbug.com/754395.
11939TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
11940 MockRead data_reads[] = {
11941 MockRead("HTTP/1.1 200 OK\r\n"),
11942 MockRead(kAlternativeServiceHttpHeader),
11943 MockRead("\r\n"),
11944 MockRead("hello world"),
11945 MockRead(SYNCHRONOUS, OK),
11946 };
11947
11948 HttpRequestInfo request;
11949 request.method = "GET";
11950 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1011951 request.traffic_annotation =
11952 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0811953
Ryan Sleevib8d7ea02018-05-07 20:01:0111954 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0811955 session_deps_.socket_factory->AddSocketDataProvider(&data);
11956
11957 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4911958 ssl.ssl_info.cert =
11959 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
11960 ASSERT_TRUE(ssl.ssl_info.cert);
11961 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0811962 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11963
11964 TestCompletionCallback callback;
11965
11966 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11967 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11968
11969 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11970 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11971
11972 url::SchemeHostPort test_server(request.url);
11973 HttpServerProperties* http_server_properties =
11974 session->http_server_properties();
11975 EXPECT_TRUE(
11976 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
11977
11978 EXPECT_THAT(callback.WaitForResult(), IsOk());
11979
11980 const HttpResponseInfo* response = trans.GetResponseInfo();
11981 ASSERT_TRUE(response);
11982 ASSERT_TRUE(response->headers);
11983 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11984 EXPECT_FALSE(response->was_fetched_via_spdy);
11985 EXPECT_FALSE(response->was_alpn_negotiated);
11986
11987 std::string response_data;
11988 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
11989 EXPECT_EQ("hello world", response_data);
11990
11991 EXPECT_TRUE(
11992 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
11993}
11994
bncd16676a2016-07-20 16:23:0111995TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5211996 MockRead data_reads[] = {
11997 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4311998 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5211999 MockRead("\r\n"),
12000 MockRead("hello world"),
12001 MockRead(SYNCHRONOUS, OK),
12002 };
12003
12004 HttpRequestInfo request;
12005 request.method = "GET";
bncb26024382016-06-29 02:39:4512006 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012007 request.traffic_annotation =
12008 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212009
Ryan Sleevib8d7ea02018-05-07 20:01:0112010 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212011 session_deps_.socket_factory->AddSocketDataProvider(&data);
12012
bncb26024382016-06-29 02:39:4512013 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912014 ssl.ssl_info.cert =
12015 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12016 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512017 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12018
bncc958faa2015-07-31 18:14:5212019 TestCompletionCallback callback;
12020
danakj1fd259a02016-04-16 03:17:0912021 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612022 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212023
tfarina42834112016-09-22 13:38:2012024 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112025 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212026
bncb26024382016-06-29 02:39:4512027 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012028 HttpServerProperties* http_server_properties =
12029 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412030 EXPECT_TRUE(
12031 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bncc958faa2015-07-31 18:14:5212032
robpercival214763f2016-07-01 23:27:0112033 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212034
bnc691fda62016-08-12 00:43:1612035 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212036 ASSERT_TRUE(response);
12037 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212038 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12039 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212040 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212041
12042 std::string response_data;
bnc691fda62016-08-12 00:43:1612043 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212044 EXPECT_EQ("hello world", response_data);
12045
zhongyic4de03032017-05-19 04:07:3412046 AlternativeServiceInfoVector alternative_service_info_vector =
12047 http_server_properties->GetAlternativeServiceInfos(test_server);
12048 ASSERT_EQ(1u, alternative_service_info_vector.size());
12049 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12050 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412051 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212052}
12053
bnce3dd56f2016-06-01 10:37:1112054// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0112055TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112056 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1112057 MockRead data_reads[] = {
12058 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312059 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1112060 MockRead("\r\n"),
12061 MockRead("hello world"),
12062 MockRead(SYNCHRONOUS, OK),
12063 };
12064
12065 HttpRequestInfo request;
12066 request.method = "GET";
12067 request.url = GURL("http://www.example.org/");
12068 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012069 request.traffic_annotation =
12070 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112071
Ryan Sleevib8d7ea02018-05-07 20:01:0112072 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112073 session_deps_.socket_factory->AddSocketDataProvider(&data);
12074
12075 TestCompletionCallback callback;
12076
12077 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612078 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112079
12080 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012081 HttpServerProperties* http_server_properties =
12082 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412083 EXPECT_TRUE(
12084 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnce3dd56f2016-06-01 10:37:1112085
tfarina42834112016-09-22 13:38:2012086 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112087 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12088 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1112089
bnc691fda62016-08-12 00:43:1612090 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1112091 ASSERT_TRUE(response);
12092 ASSERT_TRUE(response->headers);
12093 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12094 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212095 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1112096
12097 std::string response_data;
bnc691fda62016-08-12 00:43:1612098 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1112099 EXPECT_EQ("hello world", response_data);
12100
zhongyic4de03032017-05-19 04:07:3412101 EXPECT_TRUE(
12102 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnce3dd56f2016-06-01 10:37:1112103}
12104
bnca86731e2017-04-17 12:31:2812105// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2512106// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0112107TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2512108 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2812109 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4512110
bnc8bef8da22016-05-30 01:28:2512111 HttpRequestInfo request;
12112 request.method = "GET";
bncb26024382016-06-29 02:39:4512113 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2512114 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012115 request.traffic_annotation =
12116 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2512117
12118 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12119 StaticSocketDataProvider first_data;
12120 first_data.set_connect_data(mock_connect);
12121 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512122 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612123 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512124 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2512125
12126 MockRead data_reads[] = {
12127 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12128 MockRead(ASYNC, OK),
12129 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112130 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2512131 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12132
12133 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12134
bnc525e175a2016-06-20 12:36:4012135 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2512136 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112137 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
12138 444);
bnc8bef8da22016-05-30 01:28:2512139 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112140 http_server_properties->SetHttp2AlternativeService(
bnc8bef8da22016-05-30 01:28:2512141 url::SchemeHostPort(request.url), alternative_service, expiration);
12142
bnc691fda62016-08-12 00:43:1612143 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2512144 TestCompletionCallback callback;
12145
tfarina42834112016-09-22 13:38:2012146 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2512147 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112148 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2512149}
12150
bnce3dd56f2016-06-01 10:37:1112151// Regression test for https://crbug.com/615497:
12152// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0112153TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112154 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1112155 HttpRequestInfo request;
12156 request.method = "GET";
12157 request.url = GURL("http://www.example.org/");
12158 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012159 request.traffic_annotation =
12160 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112161
12162 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12163 StaticSocketDataProvider first_data;
12164 first_data.set_connect_data(mock_connect);
12165 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
12166
12167 MockRead data_reads[] = {
12168 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12169 MockRead(ASYNC, OK),
12170 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112171 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112172 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12173
12174 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12175
bnc525e175a2016-06-20 12:36:4012176 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1112177 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112178 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1112179 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112180 http_server_properties->SetHttp2AlternativeService(
bnce3dd56f2016-06-01 10:37:1112181 url::SchemeHostPort(request.url), alternative_service, expiration);
12182
bnc691fda62016-08-12 00:43:1612183 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112184 TestCompletionCallback callback;
12185
tfarina42834112016-09-22 13:38:2012186 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1112187 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112188 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1112189}
12190
bncd16676a2016-07-20 16:23:0112191TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0812192 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0912193 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012194 HttpServerProperties* http_server_properties =
12195 session->http_server_properties();
bncb26024382016-06-29 02:39:4512196 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2112197 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0812198 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112199 http_server_properties->SetQuicAlternativeService(
12200 test_server, alternative_service, expiration,
12201 session->params().quic_supported_versions);
zhongyic4de03032017-05-19 04:07:3412202 EXPECT_EQ(
12203 1u,
12204 http_server_properties->GetAlternativeServiceInfos(test_server).size());
bnc4f575852015-10-14 18:35:0812205
12206 // Send a clear header.
12207 MockRead data_reads[] = {
12208 MockRead("HTTP/1.1 200 OK\r\n"),
12209 MockRead("Alt-Svc: clear\r\n"),
12210 MockRead("\r\n"),
12211 MockRead("hello world"),
12212 MockRead(SYNCHRONOUS, OK),
12213 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112214 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0812215 session_deps_.socket_factory->AddSocketDataProvider(&data);
12216
bncb26024382016-06-29 02:39:4512217 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912218 ssl.ssl_info.cert =
12219 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12220 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512221 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12222
bnc4f575852015-10-14 18:35:0812223 HttpRequestInfo request;
12224 request.method = "GET";
bncb26024382016-06-29 02:39:4512225 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012226 request.traffic_annotation =
12227 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0812228
12229 TestCompletionCallback callback;
12230
bnc691fda62016-08-12 00:43:1612231 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0812232
tfarina42834112016-09-22 13:38:2012233 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112234 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0812235
bnc691fda62016-08-12 00:43:1612236 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212237 ASSERT_TRUE(response);
12238 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0812239 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12240 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212241 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0812242
12243 std::string response_data;
bnc691fda62016-08-12 00:43:1612244 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0812245 EXPECT_EQ("hello world", response_data);
12246
zhongyic4de03032017-05-19 04:07:3412247 EXPECT_TRUE(
12248 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnc4f575852015-10-14 18:35:0812249}
12250
bncd16676a2016-07-20 16:23:0112251TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5212252 MockRead data_reads[] = {
12253 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312254 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
12255 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5212256 MockRead("hello world"),
12257 MockRead(SYNCHRONOUS, OK),
12258 };
12259
12260 HttpRequestInfo request;
12261 request.method = "GET";
bncb26024382016-06-29 02:39:4512262 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012263 request.traffic_annotation =
12264 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212265
Ryan Sleevib8d7ea02018-05-07 20:01:0112266 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212267 session_deps_.socket_factory->AddSocketDataProvider(&data);
12268
bncb26024382016-06-29 02:39:4512269 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912270 ssl.ssl_info.cert =
12271 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12272 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512273 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12274
bncc958faa2015-07-31 18:14:5212275 TestCompletionCallback callback;
12276
danakj1fd259a02016-04-16 03:17:0912277 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612278 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212279
tfarina42834112016-09-22 13:38:2012280 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112281 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212282
bncb26024382016-06-29 02:39:4512283 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4012284 HttpServerProperties* http_server_properties =
12285 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412286 EXPECT_TRUE(
12287 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bncc958faa2015-07-31 18:14:5212288
robpercival214763f2016-07-01 23:27:0112289 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212290
bnc691fda62016-08-12 00:43:1612291 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212292 ASSERT_TRUE(response);
12293 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212294 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12295 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212296 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212297
12298 std::string response_data;
bnc691fda62016-08-12 00:43:1612299 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212300 EXPECT_EQ("hello world", response_data);
12301
zhongyic4de03032017-05-19 04:07:3412302 AlternativeServiceInfoVector alternative_service_info_vector =
12303 http_server_properties->GetAlternativeServiceInfos(test_server);
12304 ASSERT_EQ(2u, alternative_service_info_vector.size());
12305
12306 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
12307 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412308 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412309 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
12310 1234);
12311 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5412312 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5212313}
12314
bncd16676a2016-07-20 16:23:0112315TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612316 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212317 HostPortPair alternative("alternative.example.org", 443);
12318 std::string origin_url = "https://origin.example.org:443";
12319 std::string alternative_url = "https://alternative.example.org:443";
12320
12321 // Negotiate HTTP/1.1 with alternative.example.org.
12322 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612323 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212324 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12325
12326 // HTTP/1.1 data for request.
12327 MockWrite http_writes[] = {
12328 MockWrite("GET / HTTP/1.1\r\n"
12329 "Host: alternative.example.org\r\n"
12330 "Connection: keep-alive\r\n\r\n"),
12331 };
12332
12333 MockRead http_reads[] = {
12334 MockRead("HTTP/1.1 200 OK\r\n"
12335 "Content-Type: text/html; charset=iso-8859-1\r\n"
12336 "Content-Length: 40\r\n\r\n"
12337 "first HTTP/1.1 response from alternative"),
12338 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112339 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212340 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12341
12342 StaticSocketDataProvider data_refused;
12343 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12344 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12345
zhongyi3d4a55e72016-04-22 20:36:4612346 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0912347 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012348 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212349 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112350 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0212351 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112352 http_server_properties->SetQuicAlternativeService(
12353 server, alternative_service, expiration,
12354 HttpNetworkSession::Params().quic_supported_versions);
zhongyi48704c182015-12-07 07:52:0212355 // Mark the QUIC alternative service as broken.
12356 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
12357
zhongyi48704c182015-12-07 07:52:0212358 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612359 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212360 request.method = "GET";
12361 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1012362 request.traffic_annotation =
12363 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12364
zhongyi48704c182015-12-07 07:52:0212365 TestCompletionCallback callback;
12366 NetErrorDetails details;
12367 EXPECT_FALSE(details.quic_broken);
12368
tfarina42834112016-09-22 13:38:2012369 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612370 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212371 EXPECT_TRUE(details.quic_broken);
12372}
12373
bncd16676a2016-07-20 16:23:0112374TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612375 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212376 HostPortPair alternative1("alternative1.example.org", 443);
12377 HostPortPair alternative2("alternative2.example.org", 443);
12378 std::string origin_url = "https://origin.example.org:443";
12379 std::string alternative_url1 = "https://alternative1.example.org:443";
12380 std::string alternative_url2 = "https://alternative2.example.org:443";
12381
12382 // Negotiate HTTP/1.1 with alternative1.example.org.
12383 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612384 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212385 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12386
12387 // HTTP/1.1 data for request.
12388 MockWrite http_writes[] = {
12389 MockWrite("GET / HTTP/1.1\r\n"
12390 "Host: alternative1.example.org\r\n"
12391 "Connection: keep-alive\r\n\r\n"),
12392 };
12393
12394 MockRead http_reads[] = {
12395 MockRead("HTTP/1.1 200 OK\r\n"
12396 "Content-Type: text/html; charset=iso-8859-1\r\n"
12397 "Content-Length: 40\r\n\r\n"
12398 "first HTTP/1.1 response from alternative1"),
12399 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112400 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212401 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12402
12403 StaticSocketDataProvider data_refused;
12404 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12405 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12406
danakj1fd259a02016-04-16 03:17:0912407 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012408 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212409 session->http_server_properties();
12410
zhongyi3d4a55e72016-04-22 20:36:4612411 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0212412 AlternativeServiceInfoVector alternative_service_info_vector;
12413 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12414
bnc3472afd2016-11-17 15:27:2112415 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2112416 alternative_service_info_vector.push_back(
12417 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12418 alternative_service1, expiration,
12419 session->params().quic_supported_versions));
bnc3472afd2016-11-17 15:27:2112420 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2112421 alternative_service_info_vector.push_back(
12422 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12423 alternative_service2, expiration,
12424 session->params().quic_supported_versions));
zhongyi48704c182015-12-07 07:52:0212425
12426 http_server_properties->SetAlternativeServices(
zhongyi3d4a55e72016-04-22 20:36:4612427 server, alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0212428
12429 // Mark one of the QUIC alternative service as broken.
12430 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
zhongyic4de03032017-05-19 04:07:3412431 EXPECT_EQ(2u,
12432 http_server_properties->GetAlternativeServiceInfos(server).size());
zhongyi48704c182015-12-07 07:52:0212433
zhongyi48704c182015-12-07 07:52:0212434 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612435 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212436 request.method = "GET";
12437 request.url = GURL(origin_url);
Ramin Halavatib5e433e2018-02-07 07:41:1012438 request.traffic_annotation =
12439 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12440
zhongyi48704c182015-12-07 07:52:0212441 TestCompletionCallback callback;
12442 NetErrorDetails details;
12443 EXPECT_FALSE(details.quic_broken);
12444
tfarina42834112016-09-22 13:38:2012445 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612446 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212447 EXPECT_FALSE(details.quic_broken);
12448}
12449
bncd16676a2016-07-20 16:23:0112450TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4212451 HttpRequestInfo request;
12452 request.method = "GET";
bncb26024382016-06-29 02:39:4512453 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012454 request.traffic_annotation =
12455 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4212456
[email protected]d973e99a2012-02-17 21:02:3612457 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4212458 StaticSocketDataProvider first_data;
12459 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712460 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512461 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612462 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4212464
12465 MockRead data_reads[] = {
12466 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12467 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612468 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4212469 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112470 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712471 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4212472
danakj1fd259a02016-04-16 03:17:0912473 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4212474
bnc525e175a2016-06-20 12:36:4012475 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312476 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4612477 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1112478 // Port must be < 1024, or the header will be ignored (since initial port was
12479 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2112480 // Port is ignored by MockConnect anyway.
12481 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12482 666);
bnc7dc7e1b42015-07-28 14:43:1212483 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112484 http_server_properties->SetHttp2AlternativeService(
12485 server, alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4212486
bnc691fda62016-08-12 00:43:1612487 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112488 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4212489
tfarina42834112016-09-22 13:38:2012490 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112491 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12492 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4212493
bnc691fda62016-08-12 00:43:1612494 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212495 ASSERT_TRUE(response);
12496 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4212497 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12498
12499 std::string response_data;
bnc691fda62016-08-12 00:43:1612500 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4212501 EXPECT_EQ("hello world", response_data);
12502
zhongyic4de03032017-05-19 04:07:3412503 const AlternativeServiceInfoVector alternative_service_info_vector =
12504 http_server_properties->GetAlternativeServiceInfos(server);
12505 ASSERT_EQ(1u, alternative_service_info_vector.size());
12506 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412507 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412508 EXPECT_TRUE(
12509 http_server_properties->IsAlternativeServiceBroken(alternative_service));
[email protected]564b4912010-03-09 16:30:4212510}
12511
bnc55ff9da2015-08-19 18:42:3512512// Ensure that we are not allowed to redirect traffic via an alternate protocol
12513// to an unrestricted (port >= 1024) when the original traffic was on a
12514// restricted port (port < 1024). Ensure that we can redirect in all other
12515// cases.
bncd16676a2016-07-20 16:23:0112516TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1112517 HttpRequestInfo restricted_port_request;
12518 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512519 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112520 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012521 restricted_port_request.traffic_annotation =
12522 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112523
[email protected]d973e99a2012-02-17 21:02:3612524 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112525 StaticSocketDataProvider first_data;
12526 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712527 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112528
12529 MockRead data_reads[] = {
12530 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12531 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612532 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112533 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112534 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712535 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512536 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612537 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512538 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112539
danakj1fd259a02016-04-16 03:17:0912540 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112541
bnc525e175a2016-06-20 12:36:4012542 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312543 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112544 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112545 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12546 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212547 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112548 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612549 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012550 expiration);
[email protected]3912662a32011-10-04 00:51:1112551
bnc691fda62016-08-12 00:43:1612552 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112553 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112554
tfarina42834112016-09-22 13:38:2012555 int rv = trans.Start(&restricted_port_request, callback.callback(),
12556 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112557 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112558 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0112559 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1912560}
[email protected]3912662a32011-10-04 00:51:1112561
bnc55ff9da2015-08-19 18:42:3512562// Ensure that we are allowed to redirect traffic via an alternate protocol to
12563// an unrestricted (port >= 1024) when the original traffic was on a restricted
12564// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0112565TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0712566 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1912567
12568 HttpRequestInfo restricted_port_request;
12569 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512570 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1912571 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012572 restricted_port_request.traffic_annotation =
12573 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1912574
12575 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12576 StaticSocketDataProvider first_data;
12577 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712578 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1912579
12580 MockRead data_reads[] = {
12581 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12582 MockRead("hello world"),
12583 MockRead(ASYNC, OK),
12584 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112585 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712586 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512587 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612588 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512589 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1912590
danakj1fd259a02016-04-16 03:17:0912591 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1912592
bnc525e175a2016-06-20 12:36:4012593 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1912594 session->http_server_properties();
12595 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112596 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12597 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212598 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112599 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612600 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012601 expiration);
[email protected]c54c6962013-02-01 04:53:1912602
bnc691fda62016-08-12 00:43:1612603 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1912604 TestCompletionCallback callback;
12605
tfarina42834112016-09-22 13:38:2012606 EXPECT_EQ(ERR_IO_PENDING,
12607 trans.Start(&restricted_port_request, callback.callback(),
12608 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1912609 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0112610 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112611}
12612
bnc55ff9da2015-08-19 18:42:3512613// Ensure that we are not allowed to redirect traffic via an alternate protocol
12614// to an unrestricted (port >= 1024) when the original traffic was on a
12615// restricted port (port < 1024). Ensure that we can redirect in all other
12616// cases.
bncd16676a2016-07-20 16:23:0112617TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1112618 HttpRequestInfo restricted_port_request;
12619 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512620 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112621 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012622 restricted_port_request.traffic_annotation =
12623 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112624
[email protected]d973e99a2012-02-17 21:02:3612625 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112626 StaticSocketDataProvider first_data;
12627 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712628 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112629
12630 MockRead data_reads[] = {
12631 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12632 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612633 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112634 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112635 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712636 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112637
bncb26024382016-06-29 02:39:4512638 SSLSocketDataProvider ssl(ASYNC, OK);
12639 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12640
danakj1fd259a02016-04-16 03:17:0912641 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112642
bnc525e175a2016-06-20 12:36:4012643 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312644 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112645 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112646 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12647 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212648 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112649 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612650 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012651 expiration);
[email protected]3912662a32011-10-04 00:51:1112652
bnc691fda62016-08-12 00:43:1612653 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112654 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112655
tfarina42834112016-09-22 13:38:2012656 int rv = trans.Start(&restricted_port_request, callback.callback(),
12657 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112658 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112659 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112660 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112661}
12662
bnc55ff9da2015-08-19 18:42:3512663// Ensure that we are not allowed to redirect traffic via an alternate protocol
12664// to an unrestricted (port >= 1024) when the original traffic was on a
12665// restricted port (port < 1024). Ensure that we can redirect in all other
12666// cases.
bncd16676a2016-07-20 16:23:0112667TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1112668 HttpRequestInfo unrestricted_port_request;
12669 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512670 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112671 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012672 unrestricted_port_request.traffic_annotation =
12673 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112674
[email protected]d973e99a2012-02-17 21:02:3612675 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112676 StaticSocketDataProvider first_data;
12677 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712678 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112679
12680 MockRead data_reads[] = {
12681 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12682 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612683 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112684 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112685 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712686 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512687 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612688 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512689 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112690
danakj1fd259a02016-04-16 03:17:0912691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112692
bnc525e175a2016-06-20 12:36:4012693 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312694 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112695 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112696 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12697 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212698 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112699 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612700 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012701 expiration);
[email protected]3912662a32011-10-04 00:51:1112702
bnc691fda62016-08-12 00:43:1612703 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112704 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112705
bnc691fda62016-08-12 00:43:1612706 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012707 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112708 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112709 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112710 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112711}
12712
bnc55ff9da2015-08-19 18:42:3512713// Ensure that we are not allowed to redirect traffic via an alternate protocol
12714// to an unrestricted (port >= 1024) when the original traffic was on a
12715// restricted port (port < 1024). Ensure that we can redirect in all other
12716// cases.
bncd16676a2016-07-20 16:23:0112717TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1112718 HttpRequestInfo unrestricted_port_request;
12719 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512720 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112721 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1012722 unrestricted_port_request.traffic_annotation =
12723 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112724
[email protected]d973e99a2012-02-17 21:02:3612725 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112726 StaticSocketDataProvider first_data;
12727 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712728 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112729
12730 MockRead data_reads[] = {
12731 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12732 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612733 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112734 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112735 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712736 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112737
bncb26024382016-06-29 02:39:4512738 SSLSocketDataProvider ssl(ASYNC, OK);
12739 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12740
danakj1fd259a02016-04-16 03:17:0912741 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112742
bnc525e175a2016-06-20 12:36:4012743 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312744 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2212745 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2112746 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12747 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212748 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112749 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612750 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012751 expiration);
[email protected]3912662a32011-10-04 00:51:1112752
bnc691fda62016-08-12 00:43:1612753 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112754 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112755
bnc691fda62016-08-12 00:43:1612756 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012757 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112758 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112759 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0112760 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112761}
12762
bnc55ff9da2015-08-19 18:42:3512763// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2112764// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
12765// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0112766TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0212767 HttpRequestInfo request;
12768 request.method = "GET";
bncce36dca22015-04-21 22:11:2312769 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012770 request.traffic_annotation =
12771 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0212772
12773 // The alternate protocol request will error out before we attempt to connect,
12774 // so only the standard HTTP request will try to connect.
12775 MockRead data_reads[] = {
12776 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12777 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612778 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0212779 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112780 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712781 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0212782
danakj1fd259a02016-04-16 03:17:0912783 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0212784
bnc525e175a2016-06-20 12:36:4012785 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0212786 session->http_server_properties();
12787 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2112788 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12789 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1212790 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112791 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612792 url::SchemeHostPort(request.url), alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0212793
bnc691fda62016-08-12 00:43:1612794 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0212795 TestCompletionCallback callback;
12796
tfarina42834112016-09-22 13:38:2012797 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112798 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0212799 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0112800 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212801
bnc691fda62016-08-12 00:43:1612802 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212803 ASSERT_TRUE(response);
12804 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0212805 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12806
12807 std::string response_data;
bnc691fda62016-08-12 00:43:1612808 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212809 EXPECT_EQ("hello world", response_data);
12810}
12811
bncd16676a2016-07-20 16:23:0112812TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5412813 HttpRequestInfo request;
12814 request.method = "GET";
bncb26024382016-06-29 02:39:4512815 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012816 request.traffic_annotation =
12817 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5412818
12819 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212820 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312821 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212822 MockRead("\r\n"),
12823 MockRead("hello world"),
12824 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12825 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5412826
Ryan Sleevib8d7ea02018-05-07 20:01:0112827 StaticSocketDataProvider first_transaction(data_reads,
12828 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712829 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4512830 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612831 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512832 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5412833
bnc032658ba2016-09-26 18:17:1512834 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5412835
Ryan Hamilton0239aac2018-05-19 00:03:1312836 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4512837 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4112838 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5412839
Raul Tambre94493c652019-03-11 17:18:3512840 spdy::SpdySerializedFrame resp(
12841 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1312842 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5412843 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112844 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5412845 };
12846
Ryan Sleevib8d7ea02018-05-07 20:01:0112847 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0712848 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5412849
[email protected]d973e99a2012-02-17 21:02:3612850 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0112851 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5512852 hanging_non_alternate_protocol_socket.set_connect_data(
12853 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0712854 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5512855 &hanging_non_alternate_protocol_socket);
12856
[email protected]49639fa2011-12-20 23:22:4112857 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5412858
danakj1fd259a02016-04-16 03:17:0912859 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812860 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912861 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412862
tfarina42834112016-09-22 13:38:2012863 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112864 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12865 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412866
12867 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212868 ASSERT_TRUE(response);
12869 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5412870 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12871
12872 std::string response_data;
robpercival214763f2016-07-01 23:27:0112873 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412874 EXPECT_EQ("hello world", response_data);
12875
bnc87dcefc2017-05-25 12:47:5812876 trans =
Jeremy Roman0579ed62017-08-29 15:56:1912877 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412878
tfarina42834112016-09-22 13:38:2012879 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112880 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12881 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412882
12883 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212884 ASSERT_TRUE(response);
12885 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212886 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5312887 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212888 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5412889
robpercival214763f2016-07-01 23:27:0112890 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412891 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5412892}
12893
bncd16676a2016-07-20 16:23:0112894TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5512895 HttpRequestInfo request;
12896 request.method = "GET";
bncb26024382016-06-29 02:39:4512897 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1012898 request.traffic_annotation =
12899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5512900
bncb26024382016-06-29 02:39:4512901 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5512902 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212903 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312904 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212905 MockRead("\r\n"),
12906 MockRead("hello world"),
12907 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12908 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5512909 };
12910
Ryan Sleevib8d7ea02018-05-07 20:01:0112911 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4512912 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5512913
bncb26024382016-06-29 02:39:4512914 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912915 ssl_http11.ssl_info.cert =
12916 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12917 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4512918 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
12919
12920 // Second transaction starts an alternative and a non-alternative Job.
12921 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3612922 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0112923 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1812924 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1812925 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
12926
Ryan Sleevib8d7ea02018-05-07 20:01:0112927 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1812928 hanging_socket2.set_connect_data(never_finishing_connect);
12929 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5512930
bncb26024382016-06-29 02:39:4512931 // Third transaction starts an alternative and a non-alternative job.
12932 // The non-alternative job hangs, but the alternative one succeeds.
12933 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1312934 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4512935 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1312936 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4512937 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5512938 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4112939 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5512940 };
Raul Tambre94493c652019-03-11 17:18:3512941 spdy::SpdySerializedFrame resp1(
12942 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1312943 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3512944 spdy::SpdySerializedFrame resp2(
12945 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1312946 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5512947 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112948 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
12949 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1312950 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5512951 };
12952
Ryan Sleevib8d7ea02018-05-07 20:01:0112953 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0712954 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5512955
bnc032658ba2016-09-26 18:17:1512956 AddSSLSocketData();
bncb26024382016-06-29 02:39:4512957
Ryan Sleevib8d7ea02018-05-07 20:01:0112958 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1812959 hanging_socket3.set_connect_data(never_finishing_connect);
12960 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5512961
danakj1fd259a02016-04-16 03:17:0912962 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4112963 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5012964 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5512965
tfarina42834112016-09-22 13:38:2012966 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112967 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12968 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5512969
12970 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5212971 ASSERT_TRUE(response);
12972 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5512973 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12974
12975 std::string response_data;
robpercival214763f2016-07-01 23:27:0112976 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512977 EXPECT_EQ("hello world", response_data);
12978
[email protected]49639fa2011-12-20 23:22:4112979 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5012980 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2012981 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112982 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5512983
[email protected]49639fa2011-12-20 23:22:4112984 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5012985 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2012986 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112987 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5512988
robpercival214763f2016-07-01 23:27:0112989 EXPECT_THAT(callback2.WaitForResult(), IsOk());
12990 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5512991
12992 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5212993 ASSERT_TRUE(response);
12994 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212995 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5512996 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212997 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0112998 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512999 EXPECT_EQ("hello!", response_data);
13000
13001 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5213002 ASSERT_TRUE(response);
13003 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213004 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5513005 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213006 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0113007 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513008 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5513009}
13010
bncd16676a2016-07-20 16:23:0113011TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5313012 session_deps_.host_resolver->set_synchronous_mode(true);
13013
[email protected]2d6728692011-03-12 01:39:5513014 HttpRequestInfo request;
13015 request.method = "GET";
bncb26024382016-06-29 02:39:4513016 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013017 request.traffic_annotation =
13018 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513019
13020 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213021 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313022 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213023 MockRead("\r\n"),
13024 MockRead("hello world"),
13025 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13026 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513027 };
13028
Ryan Sleevib8d7ea02018-05-07 20:01:0113029 StaticSocketDataProvider first_transaction(data_reads,
13030 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713031 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513032
[email protected]8ddf8322012-02-23 18:08:0613033 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913034 ssl.ssl_info.cert =
13035 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13036 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713037 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513038
[email protected]d973e99a2012-02-17 21:02:3613039 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113040 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513041 hanging_alternate_protocol_socket.set_connect_data(
13042 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713043 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513044 &hanging_alternate_protocol_socket);
13045
bncb26024382016-06-29 02:39:4513046 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0113047 StaticSocketDataProvider second_transaction(data_reads,
13048 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1813049 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4513050 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513051
[email protected]49639fa2011-12-20 23:22:4113052 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5513053
danakj1fd259a02016-04-16 03:17:0913054 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813055 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913056 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513057
tfarina42834112016-09-22 13:38:2013058 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113059 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13060 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513061
13062 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213063 ASSERT_TRUE(response);
13064 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513065 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13066
13067 std::string response_data;
robpercival214763f2016-07-01 23:27:0113068 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513069 EXPECT_EQ("hello world", response_data);
13070
bnc87dcefc2017-05-25 12:47:5813071 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913072 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513073
tfarina42834112016-09-22 13:38:2013074 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113075 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13076 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513077
13078 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213079 ASSERT_TRUE(response);
13080 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513081 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13082 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213083 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5513084
robpercival214763f2016-07-01 23:27:0113085 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513086 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5513087}
13088
bnc2e884782016-08-11 19:45:1913089// Test that proxy is resolved using the origin url,
13090// regardless of the alternative server.
13091TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
13092 // Configure proxy to bypass www.example.org, which is the origin URL.
13093 ProxyConfig proxy_config;
13094 proxy_config.proxy_rules().ParseFromString("myproxy:70");
13095 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4913096 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
13097 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1913098
13099 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1913100 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1913101 &capturing_proxy_resolver);
13102
13103 TestNetLog net_log;
13104
Bence Béky53a5aef2018-03-29 21:54:1213105 session_deps_.proxy_resolution_service =
13106 std::make_unique<ProxyResolutionService>(
13107 std::move(proxy_config_service), std::move(proxy_resolver_factory),
13108 &net_log);
bnc2e884782016-08-11 19:45:1913109
13110 session_deps_.net_log = &net_log;
13111
13112 // Configure alternative service with a hostname that is not bypassed by the
13113 // proxy.
13114 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13115 HttpServerProperties* http_server_properties =
13116 session->http_server_properties();
13117 url::SchemeHostPort server("https", "www.example.org", 443);
13118 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2113119 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1913120 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113121 http_server_properties->SetHttp2AlternativeService(
13122 server, alternative_service, expiration);
bnc2e884782016-08-11 19:45:1913123
13124 // Non-alternative job should hang.
13125 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113126 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1913127 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
13128 session_deps_.socket_factory->AddSocketDataProvider(
13129 &hanging_alternate_protocol_socket);
13130
bnc032658ba2016-09-26 18:17:1513131 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1913132
13133 HttpRequestInfo request;
13134 request.method = "GET";
13135 request.url = GURL("https://www.example.org/");
13136 request.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1013137 request.traffic_annotation =
13138 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1913139
Ryan Hamilton0239aac2018-05-19 00:03:1313140 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1913141 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
13142
13143 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
13144
Ryan Hamilton0239aac2018-05-19 00:03:1313145 spdy::SpdySerializedFrame resp(
13146 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
13147 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1913148 MockRead spdy_reads[] = {
13149 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
13150 };
13151
Ryan Sleevib8d7ea02018-05-07 20:01:0113152 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1913153 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
13154
13155 TestCompletionCallback callback;
13156
13157 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13158
tfarina42834112016-09-22 13:38:2013159 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1913160 EXPECT_THAT(callback.GetResult(rv), IsOk());
13161
13162 const HttpResponseInfo* response = trans.GetResponseInfo();
13163 ASSERT_TRUE(response);
13164 ASSERT_TRUE(response->headers);
13165 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
13166 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213167 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1913168
13169 std::string response_data;
13170 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13171 EXPECT_EQ("hello!", response_data);
13172
13173 // Origin host bypasses proxy, no resolution should have happened.
13174 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
13175}
13176
bncd16676a2016-07-20 16:23:0113177TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1113178 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4213179 proxy_config.set_auto_detect(true);
13180 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1113181
sammc5dd160c2015-04-02 02:43:1313182 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4913183 session_deps_.proxy_resolution_service =
13184 std::make_unique<ProxyResolutionService>(
13185 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
13186 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
13187 std::make_unique<CapturingProxyResolverFactory>(
13188 &capturing_proxy_resolver),
13189 nullptr);
vishal.b62985ca92015-04-17 08:45:5113190 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0713191 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1113192
13193 HttpRequestInfo request;
13194 request.method = "GET";
bncb26024382016-06-29 02:39:4513195 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013196 request.traffic_annotation =
13197 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1113198
13199 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213200 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313201 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213202 MockRead("\r\n"),
13203 MockRead("hello world"),
13204 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13205 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1113206 };
13207
Ryan Sleevib8d7ea02018-05-07 20:01:0113208 StaticSocketDataProvider first_transaction(data_reads,
13209 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713210 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513211 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613212 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513213 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1113214
bnc032658ba2016-09-26 18:17:1513215 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1113216
Ryan Hamilton0239aac2018-05-19 00:03:1313217 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513218 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1113219 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313220 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2513221 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13222 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1313223 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4113224 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1113225 };
13226
[email protected]d911f1b2010-05-05 22:39:4213227 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
13228
Raul Tambre94493c652019-03-11 17:18:3513229 spdy::SpdySerializedFrame resp(
13230 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313231 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1113232 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113233 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
13234 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1113235 };
13236
Ryan Sleevib8d7ea02018-05-07 20:01:0113237 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713238 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1113239
[email protected]d973e99a2012-02-17 21:02:3613240 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113241 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513242 hanging_non_alternate_protocol_socket.set_connect_data(
13243 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713244 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513245 &hanging_non_alternate_protocol_socket);
13246
[email protected]49639fa2011-12-20 23:22:4113247 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1113248
danakj1fd259a02016-04-16 03:17:0913249 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813250 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913251 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113252
tfarina42834112016-09-22 13:38:2013253 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4113254 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13255 EXPECT_THAT(callback.WaitForResult(), IsOk());
13256
13257 const HttpResponseInfo* response = trans->GetResponseInfo();
13258 ASSERT_TRUE(response);
13259 ASSERT_TRUE(response->headers);
13260 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
13261 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213262 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4113263
13264 std::string response_data;
13265 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
13266 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1113267
bnc87dcefc2017-05-25 12:47:5813268 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913269 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113270
tfarina42834112016-09-22 13:38:2013271 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113272 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13273 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1113274
mmenkea2dcd3bf2016-08-16 21:49:4113275 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213276 ASSERT_TRUE(response);
13277 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213278 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313279 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213280 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1113281
robpercival214763f2016-07-01 23:27:0113282 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1113283 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4513284 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
13285 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313286 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2313287 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313288 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1113289
[email protected]029c83b62013-01-24 05:28:2013290 LoadTimingInfo load_timing_info;
13291 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
13292 TestLoadTimingNotReusedWithPac(load_timing_info,
13293 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1113294}
[email protected]631f1322010-04-30 17:59:1113295
bncd16676a2016-07-20 16:23:0113296TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4813297 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5413298 HttpRequestInfo request;
13299 request.method = "GET";
bncb26024382016-06-29 02:39:4513300 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1013301 request.traffic_annotation =
13302 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413303
13304 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213305 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313306 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213307 MockRead("\r\n"),
13308 MockRead("hello world"),
13309 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5413310 };
13311
Ryan Sleevib8d7ea02018-05-07 20:01:0113312 StaticSocketDataProvider first_transaction(data_reads,
13313 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713314 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513315 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613316 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513317 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413318
bnc032658ba2016-09-26 18:17:1513319 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413320
Ryan Hamilton0239aac2018-05-19 00:03:1313321 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513322 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113323 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413324
Raul Tambre94493c652019-03-11 17:18:3513325 spdy::SpdySerializedFrame resp(
13326 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313327 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413328 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113329 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413330 };
13331
Ryan Sleevib8d7ea02018-05-07 20:01:0113332 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713333 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413334
[email protected]83039bb2011-12-09 18:43:5513335 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413336
danakj1fd259a02016-04-16 03:17:0913337 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5413338
bnc87dcefc2017-05-25 12:47:5813339 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913340 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413341
tfarina42834112016-09-22 13:38:2013342 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113343 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13344 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413345
13346 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213347 ASSERT_TRUE(response);
13348 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413349 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13350
13351 std::string response_data;
robpercival214763f2016-07-01 23:27:0113352 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413353 EXPECT_EQ("hello world", response_data);
13354
13355 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2513356 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4013357 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1113358 PRIVACY_MODE_DISABLED,
13359 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2713360 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5213361 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3813362
bnc87dcefc2017-05-25 12:47:5813363 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913364 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413365
tfarina42834112016-09-22 13:38:2013366 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13368 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413369
13370 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213371 ASSERT_TRUE(response);
13372 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213373 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313374 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213375 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413376
robpercival214763f2016-07-01 23:27:0113377 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413378 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4213379}
13380
[email protected]044de0642010-06-17 10:42:1513381// GenerateAuthToken is a mighty big test.
13382// It tests all permutation of GenerateAuthToken behavior:
13383// - Synchronous and Asynchronous completion.
13384// - OK or error on completion.
13385// - Direct connection, non-authenticating proxy, and authenticating proxy.
13386// - HTTP or HTTPS backend (to include proxy tunneling).
13387// - Non-authenticating and authenticating backend.
13388//
[email protected]fe3b7dc2012-02-03 19:52:0913389// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1513390// problems generating an auth token for an authenticating proxy, we don't
13391// need to test all permutations of the backend server).
13392//
13393// The test proceeds by going over each of the configuration cases, and
13394// potentially running up to three rounds in each of the tests. The TestConfig
13395// specifies both the configuration for the test as well as the expectations
13396// for the results.
bncd16676a2016-07-20 16:23:0113397TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5013398 static const char kServer[] = "http://www.example.com";
13399 static const char kSecureServer[] = "https://www.example.com";
13400 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1513401
13402 enum AuthTiming {
13403 AUTH_NONE,
13404 AUTH_SYNC,
13405 AUTH_ASYNC,
13406 };
13407
13408 const MockWrite kGet(
13409 "GET / HTTP/1.1\r\n"
13410 "Host: www.example.com\r\n"
13411 "Connection: keep-alive\r\n\r\n");
13412 const MockWrite kGetProxy(
13413 "GET http://www.example.com/ HTTP/1.1\r\n"
13414 "Host: www.example.com\r\n"
13415 "Proxy-Connection: keep-alive\r\n\r\n");
13416 const MockWrite kGetAuth(
13417 "GET / HTTP/1.1\r\n"
13418 "Host: www.example.com\r\n"
13419 "Connection: keep-alive\r\n"
13420 "Authorization: auth_token\r\n\r\n");
13421 const MockWrite kGetProxyAuth(
13422 "GET http://www.example.com/ HTTP/1.1\r\n"
13423 "Host: www.example.com\r\n"
13424 "Proxy-Connection: keep-alive\r\n"
13425 "Proxy-Authorization: auth_token\r\n\r\n");
13426 const MockWrite kGetAuthThroughProxy(
13427 "GET http://www.example.com/ HTTP/1.1\r\n"
13428 "Host: www.example.com\r\n"
13429 "Proxy-Connection: keep-alive\r\n"
13430 "Authorization: auth_token\r\n\r\n");
13431 const MockWrite kGetAuthWithProxyAuth(
13432 "GET http://www.example.com/ HTTP/1.1\r\n"
13433 "Host: www.example.com\r\n"
13434 "Proxy-Connection: keep-alive\r\n"
13435 "Proxy-Authorization: auth_token\r\n"
13436 "Authorization: auth_token\r\n\r\n");
13437 const MockWrite kConnect(
13438 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713439 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513440 "Proxy-Connection: keep-alive\r\n\r\n");
13441 const MockWrite kConnectProxyAuth(
13442 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713443 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513444 "Proxy-Connection: keep-alive\r\n"
13445 "Proxy-Authorization: auth_token\r\n\r\n");
13446
13447 const MockRead kSuccess(
13448 "HTTP/1.1 200 OK\r\n"
13449 "Content-Type: text/html; charset=iso-8859-1\r\n"
13450 "Content-Length: 3\r\n\r\n"
13451 "Yes");
13452 const MockRead kFailure(
13453 "Should not be called.");
13454 const MockRead kServerChallenge(
13455 "HTTP/1.1 401 Unauthorized\r\n"
13456 "WWW-Authenticate: Mock realm=server\r\n"
13457 "Content-Type: text/html; charset=iso-8859-1\r\n"
13458 "Content-Length: 14\r\n\r\n"
13459 "Unauthorized\r\n");
13460 const MockRead kProxyChallenge(
13461 "HTTP/1.1 407 Unauthorized\r\n"
13462 "Proxy-Authenticate: Mock realm=proxy\r\n"
13463 "Proxy-Connection: close\r\n"
13464 "Content-Type: text/html; charset=iso-8859-1\r\n"
13465 "Content-Length: 14\r\n\r\n"
13466 "Unauthorized\r\n");
13467 const MockRead kProxyConnected(
13468 "HTTP/1.1 200 Connection Established\r\n\r\n");
13469
13470 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
13471 // no constructors, but the C++ compiler on Windows warns about
13472 // unspecified data in compound literals. So, moved to using constructors,
13473 // and TestRound's created with the default constructor should not be used.
13474 struct TestRound {
13475 TestRound()
Raul Tambre94493c652019-03-11 17:18:3513476 : expected_rv(ERR_UNEXPECTED),
13477 extra_write(nullptr),
13478 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4313479 TestRound(const MockWrite& write_arg,
13480 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1513481 int expected_rv_arg)
13482 : write(write_arg),
13483 read(read_arg),
13484 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3513485 extra_write(nullptr),
13486 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1513487 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
13488 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0113489 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1513490 : write(write_arg),
13491 read(read_arg),
13492 expected_rv(expected_rv_arg),
13493 extra_write(extra_write_arg),
13494 extra_read(extra_read_arg) {
13495 }
13496 MockWrite write;
13497 MockRead read;
13498 int expected_rv;
13499 const MockWrite* extra_write;
13500 const MockRead* extra_read;
13501 };
13502
13503 static const int kNoSSL = 500;
13504
13505 struct TestConfig {
asanka463ca4262016-11-16 02:34:3113506 int line_number;
thestig9d3bb0c2015-01-24 00:49:5113507 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1513508 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3113509 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5113510 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1513511 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3113512 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1513513 int num_auth_rounds;
13514 int first_ssl_round;
asankae2257db2016-10-11 22:03:1613515 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1513516 } test_configs[] = {
asankac93076192016-10-03 15:46:0213517 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113518 {__LINE__,
13519 nullptr,
asankac93076192016-10-03 15:46:0213520 AUTH_NONE,
13521 OK,
13522 kServer,
13523 AUTH_NONE,
13524 OK,
13525 1,
13526 kNoSSL,
13527 {TestRound(kGet, kSuccess, OK)}},
13528 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113529 {__LINE__,
13530 nullptr,
asankac93076192016-10-03 15:46:0213531 AUTH_NONE,
13532 OK,
13533 kServer,
13534 AUTH_SYNC,
13535 OK,
13536 2,
13537 kNoSSL,
13538 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513539 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113540 {__LINE__,
13541 nullptr,
asankac93076192016-10-03 15:46:0213542 AUTH_NONE,
13543 OK,
13544 kServer,
13545 AUTH_SYNC,
13546 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613547 3,
13548 kNoSSL,
13549 {TestRound(kGet, kServerChallenge, OK),
13550 TestRound(kGet, kServerChallenge, OK),
13551 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113552 {__LINE__,
13553 nullptr,
asankae2257db2016-10-11 22:03:1613554 AUTH_NONE,
13555 OK,
13556 kServer,
13557 AUTH_SYNC,
13558 ERR_UNSUPPORTED_AUTH_SCHEME,
13559 2,
13560 kNoSSL,
13561 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113562 {__LINE__,
13563 nullptr,
asankae2257db2016-10-11 22:03:1613564 AUTH_NONE,
13565 OK,
13566 kServer,
13567 AUTH_SYNC,
13568 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
13569 2,
13570 kNoSSL,
13571 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113572 {__LINE__,
13573 kProxy,
asankae2257db2016-10-11 22:03:1613574 AUTH_SYNC,
13575 ERR_FAILED,
13576 kServer,
13577 AUTH_NONE,
13578 OK,
13579 2,
13580 kNoSSL,
13581 {TestRound(kGetProxy, kProxyChallenge, OK),
13582 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113583 {__LINE__,
13584 kProxy,
asankae2257db2016-10-11 22:03:1613585 AUTH_ASYNC,
13586 ERR_FAILED,
13587 kServer,
13588 AUTH_NONE,
13589 OK,
13590 2,
13591 kNoSSL,
13592 {TestRound(kGetProxy, kProxyChallenge, OK),
13593 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113594 {__LINE__,
13595 nullptr,
asankae2257db2016-10-11 22:03:1613596 AUTH_NONE,
13597 OK,
13598 kServer,
13599 AUTH_SYNC,
13600 ERR_FAILED,
asankac93076192016-10-03 15:46:0213601 2,
13602 kNoSSL,
13603 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613604 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113605 {__LINE__,
13606 nullptr,
asankae2257db2016-10-11 22:03:1613607 AUTH_NONE,
13608 OK,
13609 kServer,
13610 AUTH_ASYNC,
13611 ERR_FAILED,
13612 2,
13613 kNoSSL,
13614 {TestRound(kGet, kServerChallenge, OK),
13615 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113616 {__LINE__,
13617 nullptr,
asankac93076192016-10-03 15:46:0213618 AUTH_NONE,
13619 OK,
13620 kServer,
13621 AUTH_ASYNC,
13622 OK,
13623 2,
13624 kNoSSL,
13625 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513626 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113627 {__LINE__,
13628 nullptr,
asankac93076192016-10-03 15:46:0213629 AUTH_NONE,
13630 OK,
13631 kServer,
13632 AUTH_ASYNC,
13633 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613634 3,
asankac93076192016-10-03 15:46:0213635 kNoSSL,
13636 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613637 // The second round uses a HttpAuthHandlerMock that always succeeds.
13638 TestRound(kGet, kServerChallenge, OK),
13639 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213640 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113641 {__LINE__,
13642 kProxy,
asankac93076192016-10-03 15:46:0213643 AUTH_NONE,
13644 OK,
13645 kServer,
13646 AUTH_NONE,
13647 OK,
13648 1,
13649 kNoSSL,
13650 {TestRound(kGetProxy, kSuccess, OK)}},
13651 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113652 {__LINE__,
13653 kProxy,
asankac93076192016-10-03 15:46:0213654 AUTH_NONE,
13655 OK,
13656 kServer,
13657 AUTH_SYNC,
13658 OK,
13659 2,
13660 kNoSSL,
13661 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513662 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113663 {__LINE__,
13664 kProxy,
asankac93076192016-10-03 15:46:0213665 AUTH_NONE,
13666 OK,
13667 kServer,
13668 AUTH_SYNC,
13669 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613670 3,
asankac93076192016-10-03 15:46:0213671 kNoSSL,
13672 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613673 TestRound(kGetProxy, kServerChallenge, OK),
13674 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113675 {__LINE__,
13676 kProxy,
asankac93076192016-10-03 15:46:0213677 AUTH_NONE,
13678 OK,
13679 kServer,
13680 AUTH_ASYNC,
13681 OK,
13682 2,
13683 kNoSSL,
13684 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513685 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113686 {__LINE__,
13687 kProxy,
asankac93076192016-10-03 15:46:0213688 AUTH_NONE,
13689 OK,
13690 kServer,
13691 AUTH_ASYNC,
13692 ERR_INVALID_AUTH_CREDENTIALS,
13693 2,
13694 kNoSSL,
13695 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613696 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213697 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113698 {__LINE__,
13699 kProxy,
asankac93076192016-10-03 15:46:0213700 AUTH_SYNC,
13701 OK,
13702 kServer,
13703 AUTH_NONE,
13704 OK,
13705 2,
13706 kNoSSL,
13707 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513708 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113709 {__LINE__,
13710 kProxy,
asankac93076192016-10-03 15:46:0213711 AUTH_SYNC,
13712 ERR_INVALID_AUTH_CREDENTIALS,
13713 kServer,
13714 AUTH_NONE,
13715 OK,
13716 2,
13717 kNoSSL,
13718 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613719 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113720 {__LINE__,
13721 kProxy,
asankac93076192016-10-03 15:46:0213722 AUTH_ASYNC,
13723 OK,
13724 kServer,
13725 AUTH_NONE,
13726 OK,
13727 2,
13728 kNoSSL,
13729 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513730 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113731 {__LINE__,
13732 kProxy,
asankac93076192016-10-03 15:46:0213733 AUTH_ASYNC,
13734 ERR_INVALID_AUTH_CREDENTIALS,
13735 kServer,
13736 AUTH_NONE,
13737 OK,
13738 2,
13739 kNoSSL,
13740 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613741 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113742 {__LINE__,
13743 kProxy,
13744 AUTH_ASYNC,
13745 ERR_INVALID_AUTH_CREDENTIALS,
13746 kServer,
13747 AUTH_NONE,
13748 OK,
13749 3,
13750 kNoSSL,
13751 {TestRound(kGetProxy, kProxyChallenge, OK),
13752 TestRound(kGetProxy, kProxyChallenge, OK),
13753 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213754 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113755 {__LINE__,
13756 kProxy,
asankac93076192016-10-03 15:46:0213757 AUTH_SYNC,
13758 OK,
13759 kServer,
13760 AUTH_SYNC,
13761 OK,
13762 3,
13763 kNoSSL,
13764 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513765 TestRound(kGetProxyAuth, kServerChallenge, OK),
13766 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113767 {__LINE__,
13768 kProxy,
asankac93076192016-10-03 15:46:0213769 AUTH_SYNC,
13770 OK,
13771 kServer,
13772 AUTH_SYNC,
13773 ERR_INVALID_AUTH_CREDENTIALS,
13774 3,
13775 kNoSSL,
13776 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513777 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613778 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113779 {__LINE__,
13780 kProxy,
asankac93076192016-10-03 15:46:0213781 AUTH_ASYNC,
13782 OK,
13783 kServer,
13784 AUTH_SYNC,
13785 OK,
13786 3,
13787 kNoSSL,
13788 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513789 TestRound(kGetProxyAuth, kServerChallenge, OK),
13790 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113791 {__LINE__,
13792 kProxy,
asankac93076192016-10-03 15:46:0213793 AUTH_ASYNC,
13794 OK,
13795 kServer,
13796 AUTH_SYNC,
13797 ERR_INVALID_AUTH_CREDENTIALS,
13798 3,
13799 kNoSSL,
13800 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513801 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613802 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113803 {__LINE__,
13804 kProxy,
asankac93076192016-10-03 15:46:0213805 AUTH_SYNC,
13806 OK,
13807 kServer,
13808 AUTH_ASYNC,
13809 OK,
13810 3,
13811 kNoSSL,
13812 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513813 TestRound(kGetProxyAuth, kServerChallenge, OK),
13814 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113815 {__LINE__,
13816 kProxy,
13817 AUTH_SYNC,
13818 ERR_INVALID_AUTH_CREDENTIALS,
13819 kServer,
13820 AUTH_ASYNC,
13821 OK,
13822 4,
13823 kNoSSL,
13824 {TestRound(kGetProxy, kProxyChallenge, OK),
13825 TestRound(kGetProxy, kProxyChallenge, OK),
13826 TestRound(kGetProxyAuth, kServerChallenge, OK),
13827 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
13828 {__LINE__,
13829 kProxy,
asankac93076192016-10-03 15:46:0213830 AUTH_SYNC,
13831 OK,
13832 kServer,
13833 AUTH_ASYNC,
13834 ERR_INVALID_AUTH_CREDENTIALS,
13835 3,
13836 kNoSSL,
13837 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513838 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613839 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113840 {__LINE__,
13841 kProxy,
asankac93076192016-10-03 15:46:0213842 AUTH_ASYNC,
13843 OK,
13844 kServer,
13845 AUTH_ASYNC,
13846 OK,
13847 3,
13848 kNoSSL,
13849 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513850 TestRound(kGetProxyAuth, kServerChallenge, OK),
13851 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113852 {__LINE__,
13853 kProxy,
asankac93076192016-10-03 15:46:0213854 AUTH_ASYNC,
13855 OK,
13856 kServer,
13857 AUTH_ASYNC,
13858 ERR_INVALID_AUTH_CREDENTIALS,
13859 3,
13860 kNoSSL,
13861 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513862 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613863 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113864 {__LINE__,
13865 kProxy,
13866 AUTH_ASYNC,
13867 ERR_INVALID_AUTH_CREDENTIALS,
13868 kServer,
13869 AUTH_ASYNC,
13870 ERR_INVALID_AUTH_CREDENTIALS,
13871 4,
13872 kNoSSL,
13873 {TestRound(kGetProxy, kProxyChallenge, OK),
13874 TestRound(kGetProxy, kProxyChallenge, OK),
13875 TestRound(kGetProxyAuth, kServerChallenge, OK),
13876 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213877 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113878 {__LINE__,
13879 nullptr,
asankac93076192016-10-03 15:46:0213880 AUTH_NONE,
13881 OK,
13882 kSecureServer,
13883 AUTH_NONE,
13884 OK,
13885 1,
13886 0,
13887 {TestRound(kGet, kSuccess, OK)}},
13888 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113889 {__LINE__,
13890 nullptr,
asankac93076192016-10-03 15:46:0213891 AUTH_NONE,
13892 OK,
13893 kSecureServer,
13894 AUTH_SYNC,
13895 OK,
13896 2,
13897 0,
13898 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513899 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113900 {__LINE__,
13901 nullptr,
asankac93076192016-10-03 15:46:0213902 AUTH_NONE,
13903 OK,
13904 kSecureServer,
13905 AUTH_SYNC,
13906 ERR_INVALID_AUTH_CREDENTIALS,
13907 2,
13908 0,
asankae2257db2016-10-11 22:03:1613909 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113910 {__LINE__,
13911 nullptr,
asankac93076192016-10-03 15:46:0213912 AUTH_NONE,
13913 OK,
13914 kSecureServer,
13915 AUTH_ASYNC,
13916 OK,
13917 2,
13918 0,
13919 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513920 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113921 {__LINE__,
13922 nullptr,
asankac93076192016-10-03 15:46:0213923 AUTH_NONE,
13924 OK,
13925 kSecureServer,
13926 AUTH_ASYNC,
13927 ERR_INVALID_AUTH_CREDENTIALS,
13928 2,
13929 0,
asankae2257db2016-10-11 22:03:1613930 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213931 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113932 {__LINE__,
13933 kProxy,
asankac93076192016-10-03 15:46:0213934 AUTH_NONE,
13935 OK,
13936 kSecureServer,
13937 AUTH_NONE,
13938 OK,
13939 1,
13940 0,
13941 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
13942 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113943 {__LINE__,
13944 kProxy,
asankac93076192016-10-03 15:46:0213945 AUTH_NONE,
13946 OK,
13947 kSecureServer,
13948 AUTH_SYNC,
13949 OK,
13950 2,
13951 0,
13952 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1513953 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113954 {__LINE__,
13955 kProxy,
asankac93076192016-10-03 15:46:0213956 AUTH_NONE,
13957 OK,
13958 kSecureServer,
13959 AUTH_SYNC,
13960 ERR_INVALID_AUTH_CREDENTIALS,
13961 2,
13962 0,
13963 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1613964 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113965 {__LINE__,
13966 kProxy,
asankac93076192016-10-03 15:46:0213967 AUTH_NONE,
13968 OK,
13969 kSecureServer,
13970 AUTH_ASYNC,
13971 OK,
13972 2,
13973 0,
13974 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1513975 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113976 {__LINE__,
13977 kProxy,
asankac93076192016-10-03 15:46:0213978 AUTH_NONE,
13979 OK,
13980 kSecureServer,
13981 AUTH_ASYNC,
13982 ERR_INVALID_AUTH_CREDENTIALS,
13983 2,
13984 0,
13985 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1613986 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213987 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113988 {__LINE__,
13989 kProxy,
asankac93076192016-10-03 15:46:0213990 AUTH_SYNC,
13991 OK,
13992 kSecureServer,
13993 AUTH_NONE,
13994 OK,
13995 2,
13996 1,
13997 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513998 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3113999 {__LINE__,
14000 kProxy,
asankac93076192016-10-03 15:46:0214001 AUTH_SYNC,
14002 ERR_INVALID_AUTH_CREDENTIALS,
14003 kSecureServer,
14004 AUTH_NONE,
14005 OK,
14006 2,
14007 kNoSSL,
14008 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614009 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114010 {__LINE__,
14011 kProxy,
asankae2257db2016-10-11 22:03:1614012 AUTH_SYNC,
14013 ERR_UNSUPPORTED_AUTH_SCHEME,
14014 kSecureServer,
14015 AUTH_NONE,
14016 OK,
14017 2,
14018 kNoSSL,
14019 {TestRound(kConnect, kProxyChallenge, OK),
14020 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114021 {__LINE__,
14022 kProxy,
asankae2257db2016-10-11 22:03:1614023 AUTH_SYNC,
14024 ERR_UNEXPECTED,
14025 kSecureServer,
14026 AUTH_NONE,
14027 OK,
14028 2,
14029 kNoSSL,
14030 {TestRound(kConnect, kProxyChallenge, OK),
14031 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114032 {__LINE__,
14033 kProxy,
asankac93076192016-10-03 15:46:0214034 AUTH_ASYNC,
14035 OK,
14036 kSecureServer,
14037 AUTH_NONE,
14038 OK,
14039 2,
14040 1,
14041 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514042 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114043 {__LINE__,
14044 kProxy,
asankac93076192016-10-03 15:46:0214045 AUTH_ASYNC,
14046 ERR_INVALID_AUTH_CREDENTIALS,
14047 kSecureServer,
14048 AUTH_NONE,
14049 OK,
14050 2,
14051 kNoSSL,
14052 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614053 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0214054 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114055 {__LINE__,
14056 kProxy,
asankac93076192016-10-03 15:46:0214057 AUTH_SYNC,
14058 OK,
14059 kSecureServer,
14060 AUTH_SYNC,
14061 OK,
14062 3,
14063 1,
14064 {TestRound(kConnect, kProxyChallenge, OK),
14065 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14066 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514067 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114068 {__LINE__,
14069 kProxy,
asankac93076192016-10-03 15:46:0214070 AUTH_SYNC,
14071 OK,
14072 kSecureServer,
14073 AUTH_SYNC,
14074 ERR_INVALID_AUTH_CREDENTIALS,
14075 3,
14076 1,
14077 {TestRound(kConnect, kProxyChallenge, OK),
14078 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14079 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614080 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114081 {__LINE__,
14082 kProxy,
asankac93076192016-10-03 15:46:0214083 AUTH_ASYNC,
14084 OK,
14085 kSecureServer,
14086 AUTH_SYNC,
14087 OK,
14088 3,
14089 1,
14090 {TestRound(kConnect, kProxyChallenge, OK),
14091 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14092 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514093 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114094 {__LINE__,
14095 kProxy,
asankac93076192016-10-03 15:46:0214096 AUTH_ASYNC,
14097 OK,
14098 kSecureServer,
14099 AUTH_SYNC,
14100 ERR_INVALID_AUTH_CREDENTIALS,
14101 3,
14102 1,
14103 {TestRound(kConnect, kProxyChallenge, OK),
14104 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14105 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614106 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114107 {__LINE__,
14108 kProxy,
asankac93076192016-10-03 15:46:0214109 AUTH_SYNC,
14110 OK,
14111 kSecureServer,
14112 AUTH_ASYNC,
14113 OK,
14114 3,
14115 1,
14116 {TestRound(kConnect, kProxyChallenge, OK),
14117 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14118 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514119 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114120 {__LINE__,
14121 kProxy,
asankac93076192016-10-03 15:46:0214122 AUTH_SYNC,
14123 OK,
14124 kSecureServer,
14125 AUTH_ASYNC,
14126 ERR_INVALID_AUTH_CREDENTIALS,
14127 3,
14128 1,
14129 {TestRound(kConnect, kProxyChallenge, OK),
14130 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14131 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614132 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114133 {__LINE__,
14134 kProxy,
asankac93076192016-10-03 15:46:0214135 AUTH_ASYNC,
14136 OK,
14137 kSecureServer,
14138 AUTH_ASYNC,
14139 OK,
14140 3,
14141 1,
14142 {TestRound(kConnect, kProxyChallenge, OK),
14143 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14144 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514145 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114146 {__LINE__,
14147 kProxy,
asankac93076192016-10-03 15:46:0214148 AUTH_ASYNC,
14149 OK,
14150 kSecureServer,
14151 AUTH_ASYNC,
14152 ERR_INVALID_AUTH_CREDENTIALS,
14153 3,
14154 1,
14155 {TestRound(kConnect, kProxyChallenge, OK),
14156 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14157 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614158 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114159 {__LINE__,
14160 kProxy,
14161 AUTH_ASYNC,
14162 ERR_INVALID_AUTH_CREDENTIALS,
14163 kSecureServer,
14164 AUTH_ASYNC,
14165 ERR_INVALID_AUTH_CREDENTIALS,
14166 4,
14167 2,
14168 {TestRound(kConnect, kProxyChallenge, OK),
14169 TestRound(kConnect, kProxyChallenge, OK),
14170 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14171 &kServerChallenge),
14172 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1514173 };
14174
asanka463ca4262016-11-16 02:34:3114175 for (const auto& test_config : test_configs) {
14176 SCOPED_TRACE(::testing::Message() << "Test config at "
14177 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0814178 HttpAuthHandlerMock::Factory* auth_factory(
14179 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714180 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4914181 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2614182
14183 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1514184 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3114185 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0814186 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14187 std::string auth_challenge = "Mock realm=proxy";
14188 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2414189 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14190 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0814191 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2014192 empty_ssl_info, origin,
14193 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814194 auth_handler->SetGenerateExpectation(
14195 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114196 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0814197 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
14198 }
[email protected]044de0642010-06-17 10:42:1514199 }
14200 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0014201 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1514202 std::string auth_challenge = "Mock realm=server";
14203 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2414204 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14205 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1514206 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014207 empty_ssl_info, origin,
14208 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514209 auth_handler->SetGenerateExpectation(
14210 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114211 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0814212 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1614213
14214 // The second handler always succeeds. It should only be used where there
14215 // are multiple auth sessions for server auth in the same network
14216 // transaction using the same auth scheme.
14217 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1914218 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1614219 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
14220 empty_ssl_info, origin,
14221 NetLogWithSource());
14222 second_handler->SetGenerateExpectation(true, OK);
14223 auth_factory->AddMockHandler(second_handler.release(),
14224 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1514225 }
14226 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5914227 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914228 ProxyResolutionService::CreateFixed(test_config.proxy_url,
14229 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514230 } else {
Bence Béky53a5aef2018-03-29 21:54:1214231 session_deps_.proxy_resolution_service =
14232 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1514233 }
14234
14235 HttpRequestInfo request;
14236 request.method = "GET";
14237 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e2018-02-07 07:41:1014238 request.traffic_annotation =
14239 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514240
danakj1fd259a02016-04-16 03:17:0914241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1514242
rchcb68dc62015-05-21 04:45:3614243 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
14244
14245 std::vector<std::vector<MockRead>> mock_reads(1);
14246 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1514247 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214248 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1514249 const TestRound& read_write_round = test_config.rounds[round];
14250
14251 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3614252 mock_reads.back().push_back(read_write_round.read);
14253 mock_writes.back().push_back(read_write_round.write);
14254
14255 // kProxyChallenge uses Proxy-Connection: close which means that the
14256 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5414257 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3614258 mock_reads.push_back(std::vector<MockRead>());
14259 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1514260 }
14261
rchcb68dc62015-05-21 04:45:3614262 if (read_write_round.extra_read) {
14263 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1514264 }
rchcb68dc62015-05-21 04:45:3614265 if (read_write_round.extra_write) {
14266 mock_writes.back().push_back(*read_write_round.extra_write);
14267 }
[email protected]044de0642010-06-17 10:42:1514268
14269 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1514270 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0714271 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1514272 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3614273 }
[email protected]044de0642010-06-17 10:42:1514274
danakj1fd259a02016-04-16 03:17:0914275 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3614276 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1914277 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0114278 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3614279 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3214280 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3614281 }
14282
mmenkecc2298e2015-12-07 18:20:1814283 // Transaction must be created after DataProviders, so it's destroyed before
14284 // they are as well.
14285 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14286
rchcb68dc62015-05-21 04:45:3614287 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214288 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3614289 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1514290 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4114291 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1514292 int rv;
14293 if (round == 0) {
tfarina42834112016-09-22 13:38:2014294 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514295 } else {
[email protected]49639fa2011-12-20 23:22:4114296 rv = trans.RestartWithAuth(
14297 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1514298 }
14299 if (rv == ERR_IO_PENDING)
14300 rv = callback.WaitForResult();
14301
14302 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1614303 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5014304 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5514305 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1514306 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
14307 continue;
14308 }
14309 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5814310 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1514311 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5814312 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1614313 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1514314 }
14315 }
[email protected]e5ae96a2010-04-14 20:12:4514316 }
14317}
14318
bncd16676a2016-07-20 16:23:0114319TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1414320 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1414321 HttpAuthHandlerMock::Factory* auth_factory(
14322 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714323 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1214324 session_deps_.proxy_resolution_service =
14325 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0714326 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1414327
14328 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14329 auth_handler->set_connection_based(true);
14330 std::string auth_challenge = "Mock realm=server";
14331 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2414332 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14333 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4914334 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1414335 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014336 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814337 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1414338
[email protected]c871bce92010-07-15 21:51:1414339 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3514340 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1414341 HttpRequestInfo request;
14342 request.method = "GET";
14343 request.url = origin;
Ramin Halavatib5e433e2018-02-07 07:41:1014344 request.traffic_annotation =
14345 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2714346
danakj1fd259a02016-04-16 03:17:0914347 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1014348
14349 // Use a TCP Socket Pool with only one connection per group. This is used
14350 // to validate that the TCP socket is not released to the pool between
14351 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4214352 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3614353 CommonConnectJobParams common_connect_job_params(
14354 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2814355 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5914356 50, // Max sockets for pool
14357 1, // Max sockets per group
14358 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3614359 ProxyServer::Direct(), false, // is_for_websockets
Matt Menked6fd2a52019-03-20 06:14:3614360 &common_connect_job_params, session_deps_.ssl_config_service.get());
Jeremy Roman0579ed62017-08-29 15:56:1914361 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4014362 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
14363 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4814364 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1014365
bnc691fda62016-08-12 00:43:1614366 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114367 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1414368
14369 const MockWrite kGet(
14370 "GET / HTTP/1.1\r\n"
14371 "Host: www.example.com\r\n"
14372 "Connection: keep-alive\r\n\r\n");
14373 const MockWrite kGetAuth(
14374 "GET / HTTP/1.1\r\n"
14375 "Host: www.example.com\r\n"
14376 "Connection: keep-alive\r\n"
14377 "Authorization: auth_token\r\n\r\n");
14378
14379 const MockRead kServerChallenge(
14380 "HTTP/1.1 401 Unauthorized\r\n"
14381 "WWW-Authenticate: Mock realm=server\r\n"
14382 "Content-Type: text/html; charset=iso-8859-1\r\n"
14383 "Content-Length: 14\r\n\r\n"
14384 "Unauthorized\r\n");
14385 const MockRead kSuccess(
14386 "HTTP/1.1 200 OK\r\n"
14387 "Content-Type: text/html; charset=iso-8859-1\r\n"
14388 "Content-Length: 3\r\n\r\n"
14389 "Yes");
14390
14391 MockWrite writes[] = {
14392 // First round
14393 kGet,
14394 // Second round
14395 kGetAuth,
14396 // Third round
14397 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3014398 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1014399 kGetAuth,
14400 // Competing request
14401 kGet,
[email protected]c871bce92010-07-15 21:51:1414402 };
14403 MockRead reads[] = {
14404 // First round
14405 kServerChallenge,
14406 // Second round
14407 kServerChallenge,
14408 // Third round
[email protected]eca50e122010-09-11 14:03:3014409 kServerChallenge,
14410 // Fourth round
[email protected]c871bce92010-07-15 21:51:1414411 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1014412 // Competing response
14413 kSuccess,
[email protected]c871bce92010-07-15 21:51:1414414 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114415 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0714416 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1414417
Matt Menkef6edce752019-03-19 17:21:5614418 const ClientSocketPool::GroupId kSocketGroup(
14419 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5914420 PrivacyMode::PRIVACY_MODE_DISABLED);
[email protected]7ef4cbbb2011-02-06 11:19:1014421
14422 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1414423 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2014424 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1414425 if (rv == ERR_IO_PENDING)
14426 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114427 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614428 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214429 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814430 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314431 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114432 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14433 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414434
[email protected]7ef4cbbb2011-02-06 11:19:1014435 // In between rounds, another request comes in for the same domain.
14436 // It should not be able to grab the TCP socket that trans has already
14437 // claimed.
bnc691fda62016-08-12 00:43:1614438 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114439 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2014440 rv = trans_compete.Start(&request, callback_compete.callback(),
14441 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114442 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1014443 // callback_compete.WaitForResult at this point would stall forever,
14444 // since the HttpNetworkTransaction does not release the request back to
14445 // the pool until after authentication completes.
14446
14447 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1414448 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614449 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414450 if (rv == ERR_IO_PENDING)
14451 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114452 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614453 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214454 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814455 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314456 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114457 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14458 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414459
[email protected]7ef4cbbb2011-02-06 11:19:1014460 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1414461 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614462 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414463 if (rv == ERR_IO_PENDING)
14464 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114465 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614466 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214467 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814468 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314469 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114470 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14471 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3014472
[email protected]7ef4cbbb2011-02-06 11:19:1014473 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3014474 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614475 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3014476 if (rv == ERR_IO_PENDING)
14477 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114478 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614479 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214480 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814481 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314482 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014483
asanka463ca4262016-11-16 02:34:3114484 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
14485 // auth handler should transition to a DONE state in concert with the remote
14486 // server. But that's not something we can test here with a mock handler.
14487 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
14488 auth_handler->state());
14489
[email protected]7ef4cbbb2011-02-06 11:19:1014490 // Read the body since the fourth round was successful. This will also
14491 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4414492 scoped_refptr<IOBufferWithSize> io_buf =
14493 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1614494 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014495 if (rv == ERR_IO_PENDING)
14496 rv = callback.WaitForResult();
14497 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614498 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014499 EXPECT_EQ(0, rv);
14500 // There are still 0 idle sockets, since the trans_compete transaction
14501 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314502 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014503
14504 // The competing request can now finish. Wait for the headers and then
14505 // read the body.
14506 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0114507 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614508 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014509 if (rv == ERR_IO_PENDING)
14510 rv = callback.WaitForResult();
14511 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614512 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014513 EXPECT_EQ(0, rv);
14514
14515 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314516 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1414517}
14518
[email protected]65041fa2010-05-21 06:56:5314519// This tests the case that a request is issued via http instead of spdy after
14520// npn is negotiated.
bncd16676a2016-07-20 16:23:0114521TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5314522 HttpRequestInfo request;
14523 request.method = "GET";
bncce36dca22015-04-21 22:11:2314524 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014525 request.traffic_annotation =
14526 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5314527
14528 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314529 MockWrite(
14530 "GET / HTTP/1.1\r\n"
14531 "Host: www.example.org\r\n"
14532 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5314533 };
14534
14535 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214536 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314537 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214538 MockRead("\r\n"),
14539 MockRead("hello world"),
14540 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5314541 };
14542
[email protected]8ddf8322012-02-23 18:08:0614543 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614544 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5314545
[email protected]bb88e1d32013-05-03 23:11:0714546 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5314547
Ryan Sleevib8d7ea02018-05-07 20:01:0114548 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0714549 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5314550
[email protected]49639fa2011-12-20 23:22:4114551 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5314552
danakj1fd259a02016-04-16 03:17:0914553 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614554 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5314555
tfarina42834112016-09-22 13:38:2014556 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5314557
robpercival214763f2016-07-01 23:27:0114558 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14559 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5314560
bnc691fda62016-08-12 00:43:1614561 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214562 ASSERT_TRUE(response);
14563 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5314564 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14565
14566 std::string response_data;
bnc691fda62016-08-12 00:43:1614567 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5314568 EXPECT_EQ("hello world", response_data);
14569
14570 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214571 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5314572}
[email protected]26ef6582010-06-24 02:30:4714573
bnc55ff9da2015-08-19 18:42:3514574// Simulate the SSL handshake completing with an NPN negotiation followed by an
14575// immediate server closing of the socket.
14576// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0114577TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4714578 HttpRequestInfo request;
14579 request.method = "GET";
bncce36dca22015-04-21 22:11:2314580 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014581 request.traffic_annotation =
14582 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4714583
[email protected]8ddf8322012-02-23 18:08:0614584 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614585 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0714586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4714587
Ryan Hamilton0239aac2018-05-19 00:03:1314588 spdy::SpdySerializedFrame req(
14589 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114590 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4714591
14592 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614593 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4714594 };
14595
Ryan Sleevib8d7ea02018-05-07 20:01:0114596 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714597 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4714598
[email protected]49639fa2011-12-20 23:22:4114599 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4714600
danakj1fd259a02016-04-16 03:17:0914601 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614602 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4714603
tfarina42834112016-09-22 13:38:2014604 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114605 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14606 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4714607}
[email protected]65d34382010-07-01 18:12:2614608
[email protected]795cbf82013-07-22 09:37:2714609// A subclass of HttpAuthHandlerMock that records the request URL when
14610// it gets it. This is needed since the auth handler may get destroyed
14611// before we get a chance to query it.
14612class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
14613 public:
14614 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
14615
Chris Watkins7a41d3552017-12-01 02:13:2714616 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2714617
14618 protected:
dchengb03027d2014-10-21 12:00:2014619 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
14620 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0914621 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2014622 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2714623 *url_ = request->url;
14624 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0914625 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2714626 }
14627
14628 private:
14629 GURL* url_;
14630};
14631
[email protected]8e6441ca2010-08-19 05:56:3814632// Test that if we cancel the transaction as the connection is completing, that
14633// everything tears down correctly.
bncd16676a2016-07-20 16:23:0114634TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3814635 // Setup everything about the connection to complete synchronously, so that
14636 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
14637 // for is the callback from the HttpStreamRequest.
14638 // Then cancel the transaction.
14639 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3614640 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3814641 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614642 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
14643 MockRead(SYNCHRONOUS, "hello world"),
14644 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3814645 };
14646
[email protected]8e6441ca2010-08-19 05:56:3814647 HttpRequestInfo request;
14648 request.method = "GET";
bncce36dca22015-04-21 22:11:2314649 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014650 request.traffic_annotation =
14651 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3814652
danakj1fd259a02016-04-16 03:17:0914653 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814654 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914655 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2714656
Ryan Sleevib8d7ea02018-05-07 20:01:0114657 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3814658 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714659 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3814660
[email protected]49639fa2011-12-20 23:22:4114661 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3814662
vishal.b62985ca92015-04-17 08:45:5114663 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4114664 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114665 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3814666 trans.reset(); // Cancel the transaction here.
14667
fdoray92e35a72016-06-10 15:54:5514668 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3014669}
14670
[email protected]ecab6e052014-05-16 14:58:1214671// Test that if a transaction is cancelled after receiving the headers, the
14672// stream is drained properly and added back to the socket pool. The main
14673// purpose of this test is to make sure that an HttpStreamParser can be read
14674// from after the HttpNetworkTransaction and the objects it owns have been
14675// deleted.
14676// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0114677TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1214678 MockRead data_reads[] = {
14679 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
14680 MockRead(ASYNC, "Content-Length: 2\r\n"),
14681 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
14682 MockRead(ASYNC, "1"),
14683 // 2 async reads are necessary to trigger a ReadResponseBody call after the
14684 // HttpNetworkTransaction has been deleted.
14685 MockRead(ASYNC, "2"),
14686 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
14687 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114688 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1214689 session_deps_.socket_factory->AddSocketDataProvider(&data);
14690
danakj1fd259a02016-04-16 03:17:0914691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1214692
14693 {
14694 HttpRequestInfo request;
14695 request.method = "GET";
bncce36dca22015-04-21 22:11:2314696 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014697 request.traffic_annotation =
14698 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1214699
dcheng48459ac22014-08-26 00:46:4114700 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1214701 TestCompletionCallback callback;
14702
tfarina42834112016-09-22 13:38:2014703 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114704 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1214705 callback.WaitForResult();
14706
14707 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214708 ASSERT_TRUE(response);
14709 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1214710 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14711
14712 // The transaction and HttpRequestInfo are deleted.
14713 }
14714
14715 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5514716 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1214717
14718 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4114719 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1214720}
14721
[email protected]76a505b2010-08-25 06:23:0014722// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0114723TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914724 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914725 ProxyResolutionService::CreateFixedFromPacResult(
14726 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114727 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714728 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914729 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014730
[email protected]76a505b2010-08-25 06:23:0014731 HttpRequestInfo request;
14732 request.method = "GET";
bncce36dca22015-04-21 22:11:2314733 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014734 request.traffic_annotation =
14735 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014736
14737 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2314738 MockWrite(
14739 "GET http://www.example.org/ HTTP/1.1\r\n"
14740 "Host: www.example.org\r\n"
14741 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014742 };
14743
14744 MockRead data_reads1[] = {
14745 MockRead("HTTP/1.1 200 OK\r\n"),
14746 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14747 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614748 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014749 };
14750
Ryan Sleevib8d7ea02018-05-07 20:01:0114751 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714752 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0014753
[email protected]49639fa2011-12-20 23:22:4114754 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014755
bnc691fda62016-08-12 00:43:1614756 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914757 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614758 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914759 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14760 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014761
bnc691fda62016-08-12 00:43:1614762 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114763 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014764
14765 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114766 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0014767
bnc691fda62016-08-12 00:43:1614768 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214769 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014770
14771 EXPECT_TRUE(response->headers->IsKeepAlive());
14772 EXPECT_EQ(200, response->headers->response_code());
14773 EXPECT_EQ(100, response->headers->GetContentLength());
14774 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714775 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14776 HostPortPair::FromString("myproxy:70")),
14777 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914778 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14779 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14780 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0014781 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2014782
14783 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614784 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014785 TestLoadTimingNotReusedWithPac(load_timing_info,
14786 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0014787}
14788
14789// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0114790TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914791 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914792 ProxyResolutionService::CreateFixedFromPacResult(
14793 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114794 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714795 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914796 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014797
[email protected]76a505b2010-08-25 06:23:0014798 HttpRequestInfo request;
14799 request.method = "GET";
bncce36dca22015-04-21 22:11:2314800 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014801 request.traffic_annotation =
14802 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014803
14804 // Since we have proxy, should try to establish tunnel.
14805 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1714806 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14807 "Host: www.example.org:443\r\n"
14808 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014809
rsleevidb16bb02015-11-12 23:47:1714810 MockWrite("GET / HTTP/1.1\r\n"
14811 "Host: www.example.org\r\n"
14812 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014813 };
14814
14815 MockRead data_reads1[] = {
14816 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14817
14818 MockRead("HTTP/1.1 200 OK\r\n"),
14819 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14820 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614821 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014822 };
14823
Ryan Sleevib8d7ea02018-05-07 20:01:0114824 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714825 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0614826 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0714827 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0014828
[email protected]49639fa2011-12-20 23:22:4114829 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014830
bnc691fda62016-08-12 00:43:1614831 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914832 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614833 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914834 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14835 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014836
bnc691fda62016-08-12 00:43:1614837 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114838 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014839
14840 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114841 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:4614842 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4014843 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0014844 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014845 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14846 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014847 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4014848 entries, pos,
mikecirone8b85c432016-09-08 19:11:0014849 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14850 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014851
bnc691fda62016-08-12 00:43:1614852 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214853 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014854
14855 EXPECT_TRUE(response->headers->IsKeepAlive());
14856 EXPECT_EQ(200, response->headers->response_code());
14857 EXPECT_EQ(100, response->headers->GetContentLength());
14858 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14859 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714860 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14861 HostPortPair::FromString("myproxy:70")),
14862 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914863 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14864 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14865 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2014866
14867 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614868 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014869 TestLoadTimingNotReusedWithPac(load_timing_info,
14870 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0014871}
14872
rsleevidb16bb02015-11-12 23:47:1714873// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
14874// literal host.
bncd16676a2016-07-20 16:23:0114875TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5914876 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914877 ProxyResolutionService::CreateFixedFromPacResult(
14878 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714879 BoundTestNetLog log;
14880 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914881 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1714882
14883 HttpRequestInfo request;
14884 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1514885 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e2018-02-07 07:41:1014886 request.traffic_annotation =
14887 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714888
14889 // Since we have proxy, should try to establish tunnel.
14890 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1514891 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
14892 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1714893 "Proxy-Connection: keep-alive\r\n\r\n"),
14894
14895 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1514896 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1714897 "Connection: keep-alive\r\n\r\n"),
14898 };
14899
14900 MockRead data_reads1[] = {
14901 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14902
14903 MockRead("HTTP/1.1 200 OK\r\n"),
14904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14905 MockRead("Content-Length: 100\r\n\r\n"),
14906 MockRead(SYNCHRONOUS, OK),
14907 };
14908
Ryan Sleevib8d7ea02018-05-07 20:01:0114909 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1714910 session_deps_.socket_factory->AddSocketDataProvider(&data1);
14911 SSLSocketDataProvider ssl(ASYNC, OK);
14912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14913
14914 TestCompletionCallback callback1;
14915
bnc691fda62016-08-12 00:43:1614916 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1714917
bnc691fda62016-08-12 00:43:1614918 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1714920
14921 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114922 EXPECT_THAT(rv, IsOk());
rsleevidb16bb02015-11-12 23:47:1714923 TestNetLogEntry::List entries;
14924 log.GetEntries(&entries);
14925 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014926 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14927 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1714928 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014929 entries, pos,
14930 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14931 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1714932
bnc691fda62016-08-12 00:43:1614933 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214934 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1714935
14936 EXPECT_TRUE(response->headers->IsKeepAlive());
14937 EXPECT_EQ(200, response->headers->response_code());
14938 EXPECT_EQ(100, response->headers->GetContentLength());
14939 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14940 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714941 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14942 HostPortPair::FromString("myproxy:70")),
14943 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1714944
14945 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614946 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1714947 TestLoadTimingNotReusedWithPac(load_timing_info,
14948 CONNECT_TIMING_HAS_SSL_TIMES);
14949}
14950
[email protected]76a505b2010-08-25 06:23:0014951// Test a basic HTTPS GET request through a proxy, but the server hangs up
14952// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0114953TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4914954 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
14955 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114956 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714957 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914958 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014959
[email protected]76a505b2010-08-25 06:23:0014960 HttpRequestInfo request;
14961 request.method = "GET";
bncce36dca22015-04-21 22:11:2314962 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1014963 request.traffic_annotation =
14964 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014965
14966 // Since we have proxy, should try to establish tunnel.
14967 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1714968 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14969 "Host: www.example.org:443\r\n"
14970 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014971
rsleevidb16bb02015-11-12 23:47:1714972 MockWrite("GET / HTTP/1.1\r\n"
14973 "Host: www.example.org\r\n"
14974 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014975 };
14976
14977 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0014978 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614979 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0014980 };
14981
Ryan Sleevib8d7ea02018-05-07 20:01:0114982 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714983 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0614984 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0714985 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0014986
[email protected]49639fa2011-12-20 23:22:4114987 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014988
bnc691fda62016-08-12 00:43:1614989 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5014990
bnc691fda62016-08-12 00:43:1614991 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114992 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014993
14994 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114995 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
mmenke43758e62015-05-04 21:09:4614996 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4014997 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0014998 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014999 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
15000 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015001 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4015002 entries, pos,
mikecirone8b85c432016-09-08 19:11:0015003 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
15004 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0015005}
15006
[email protected]749eefa82010-09-13 22:14:0315007// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0115008TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1315009 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4915010 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4115011 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0315012
Raul Tambre94493c652019-03-11 17:18:3515013 spdy::SpdySerializedFrame resp(
15014 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315015 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0315016 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115017 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315018 };
15019
Ryan Sleevib8d7ea02018-05-07 20:01:0115020 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715021 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315022
[email protected]8ddf8322012-02-23 18:08:0615023 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615024 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715025 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315026
danakj1fd259a02016-04-16 03:17:0915027 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315028
15029 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315030 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015031 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115032 PRIVACY_MODE_DISABLED,
15033 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2715034 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215035 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315036
15037 HttpRequestInfo request;
15038 request.method = "GET";
bncce36dca22015-04-21 22:11:2315039 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1015040 request.traffic_annotation =
15041 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0315042
bnc691fda62016-08-12 00:43:1615043 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0315044
[email protected]41d64e82013-07-03 22:44:2615045 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015046 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115047 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15048 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0315049}
15050
[email protected]73b8dd222010-11-11 19:55:2415051// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1615052// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0215053void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0715054 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2915055 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715056 request_info.url = GURL("https://www.example.com/");
15057 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915058 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015059 request_info.traffic_annotation =
15060 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715061
[email protected]8ddf8322012-02-23 18:08:0615062 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2915063 MockWrite data_writes[] = {
15064 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2415065 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115066 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715067 session_deps_.socket_factory->AddSocketDataProvider(&data);
15068 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2415069
danakj1fd259a02016-04-16 03:17:0915070 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615071 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2415072
[email protected]49639fa2011-12-20 23:22:4115073 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015074 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2915075 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2415076 rv = callback.WaitForResult();
15077 ASSERT_EQ(error, rv);
15078}
15079
bncd16676a2016-07-20 16:23:0115080TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2415081 // Just check a grab bag of cert errors.
15082 static const int kErrors[] = {
15083 ERR_CERT_COMMON_NAME_INVALID,
15084 ERR_CERT_AUTHORITY_INVALID,
15085 ERR_CERT_DATE_INVALID,
15086 };
Avi Drissman4365a4782018-12-28 19:26:2415087 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0615088 CheckErrorIsPassedBack(kErrors[i], ASYNC);
15089 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2415090 }
15091}
15092
[email protected]bd0b6772011-01-11 19:59:3015093// Ensure that a client certificate is removed from the SSL client auth
15094// cache when:
15095// 1) No proxy is involved.
15096// 2) TLS False Start is disabled.
15097// 3) The initial TLS handshake requests a client certificate.
15098// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115099TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915100 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715101 request_info.url = GURL("https://www.example.com/");
15102 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915103 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015104 request_info.traffic_annotation =
15105 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715106
[email protected]bd0b6772011-01-11 19:59:3015107 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4115108 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015109
15110 // [ssl_]data1 contains the data for the first SSL handshake. When a
15111 // CertificateRequest is received for the first time, the handshake will
15112 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2915113 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015114 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715115 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115116 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715117 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015118
15119 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
15120 // False Start is not being used, the result of the SSL handshake will be
15121 // returned as part of the SSLClientSocket::Connect() call. This test
15122 // matches the result of a server sending a handshake_failure alert,
15123 // rather than a Finished message, because it requires a client
15124 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2915125 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3015126 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715127 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0115128 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0715129 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015130
15131 // [ssl_]data3 contains the data for the third SSL handshake. When a
15132 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1315133 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
15134 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3015135 // of the HttpNetworkTransaction. Because this test failure is due to
15136 // requiring a client certificate, this fallback handshake should also
15137 // fail.
ttuttle859dc7a2015-04-23 19:42:2915138 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1315139 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3015140 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715141 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115142 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0715143 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015144
[email protected]80c75f682012-05-26 16:22:1715145 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
15146 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4215147 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
15148 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1715149 // of the HttpNetworkTransaction. Because this test failure is due to
15150 // requiring a client certificate, this fallback handshake should also
15151 // fail.
ttuttle859dc7a2015-04-23 19:42:2915152 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1715153 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715154 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115155 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0715156 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715157
danakj1fd259a02016-04-16 03:17:0915158 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615159 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015160
[email protected]bd0b6772011-01-11 19:59:3015161 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4115162 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015163 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115164 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015165
15166 // Complete the SSL handshake, which should abort due to requiring a
15167 // client certificate.
15168 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115169 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015170
15171 // Indicate that no certificate should be supplied. From the perspective
15172 // of SSLClientCertCache, NULL is just as meaningful as a real
15173 // certificate, so this is the same as supply a
15174 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515175 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115176 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015177
15178 // Ensure the certificate was added to the client auth cache before
15179 // allowing the connection to continue restarting.
15180 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415181 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4115182 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415183 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215184 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015185
15186 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715187 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15188 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015189 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115190 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015191
15192 // Ensure that the client certificate is removed from the cache on a
15193 // handshake failure.
[email protected]791879c2013-12-17 07:22:4115194 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415195 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015196}
15197
15198// Ensure that a client certificate is removed from the SSL client auth
15199// cache when:
15200// 1) No proxy is involved.
15201// 2) TLS False Start is enabled.
15202// 3) The initial TLS handshake requests a client certificate.
15203// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115204TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915205 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715206 request_info.url = GURL("https://www.example.com/");
15207 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915208 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015209 request_info.traffic_annotation =
15210 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715211
[email protected]bd0b6772011-01-11 19:59:3015212 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4115213 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015214
15215 // When TLS False Start is used, SSLClientSocket::Connect() calls will
15216 // return successfully after reading up to the peer's Certificate message.
15217 // This is to allow the caller to call SSLClientSocket::Write(), which can
15218 // enqueue application data to be sent in the same packet as the
15219 // ChangeCipherSpec and Finished messages.
15220 // The actual handshake will be finished when SSLClientSocket::Read() is
15221 // called, which expects to process the peer's ChangeCipherSpec and
15222 // Finished messages. If there was an error negotiating with the peer,
15223 // such as due to the peer requiring a client certificate when none was
15224 // supplied, the alert sent by the peer won't be processed until Read() is
15225 // called.
15226
15227 // Like the non-False Start case, when a client certificate is requested by
15228 // the peer, the handshake is aborted during the Connect() call.
15229 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2915230 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015231 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115233 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715234 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015235
15236 // When a client certificate is supplied, Connect() will not be aborted
15237 // when the peer requests the certificate. Instead, the handshake will
15238 // artificially succeed, allowing the caller to write the HTTP request to
15239 // the socket. The handshake messages are not processed until Read() is
15240 // called, which then detects that the handshake was aborted, due to the
15241 // peer sending a handshake_failure because it requires a client
15242 // certificate.
ttuttle859dc7a2015-04-23 19:42:2915243 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015244 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2915246 MockRead data2_reads[] = {
15247 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3015248 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115249 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715250 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015251
15252 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1715253 // the data for the SSL handshake once the TLSv1.1 connection falls back to
15254 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915255 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015256 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715257 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115258 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715259 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015260
[email protected]80c75f682012-05-26 16:22:1715261 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
15262 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915263 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1715264 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115266 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715267 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715268
[email protected]7799de12013-05-30 05:52:5115269 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2915270 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5115271 ssl_data5.cert_request_info = cert_request.get();
15272 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0115273 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5115274 session_deps_.socket_factory->AddSocketDataProvider(&data5);
15275
danakj1fd259a02016-04-16 03:17:0915276 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615277 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015278
[email protected]bd0b6772011-01-11 19:59:3015279 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4115280 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015281 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115282 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015283
15284 // Complete the SSL handshake, which should abort due to requiring a
15285 // client certificate.
15286 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115287 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015288
15289 // Indicate that no certificate should be supplied. From the perspective
15290 // of SSLClientCertCache, NULL is just as meaningful as a real
15291 // certificate, so this is the same as supply a
15292 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515293 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115294 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015295
15296 // Ensure the certificate was added to the client auth cache before
15297 // allowing the connection to continue restarting.
15298 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415299 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4115300 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415301 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215302 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015303
[email protected]bd0b6772011-01-11 19:59:3015304 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715305 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15306 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015307 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115308 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015309
15310 // Ensure that the client certificate is removed from the cache on a
15311 // handshake failure.
[email protected]791879c2013-12-17 07:22:4115312 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415313 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015314}
15315
[email protected]8c405132011-01-11 22:03:1815316// Ensure that a client certificate is removed from the SSL client auth
15317// cache when:
15318// 1) An HTTPS proxy is involved.
15319// 3) The HTTPS proxy requests a client certificate.
15320// 4) The client supplies an invalid/unacceptable certificate for the
15321// proxy.
bncd16676a2016-07-20 16:23:0115322TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4915323 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15324 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115325 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715326 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1815327
David Benjamin3b94b0f2019-04-25 23:07:5215328 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115329 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1815330
David Benjamin3b94b0f2019-04-25 23:07:5215331 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
15332 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2915333 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1815334 requests[0].url = GURL("https://www.example.com/");
15335 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915336 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015337 requests[0].traffic_annotation =
15338 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815339
David Benjamin3b94b0f2019-04-25 23:07:5215340 // HTTPS requests are tunneled.
15341 MockWrite https_writes[] = {
15342 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
15343 "Host: www.example.com:443\r\n"
15344 "Proxy-Connection: keep-alive\r\n\r\n"),
15345 };
15346
[email protected]8c405132011-01-11 22:03:1815347 requests[1].url = GURL("http://www.example.com/");
15348 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915349 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e2018-02-07 07:41:1015350 requests[1].traffic_annotation =
15351 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815352
David Benjamin3b94b0f2019-04-25 23:07:5215353 // HTTP requests are not.
15354 MockWrite http_writes[] = {
15355 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
15356 "Host: www.example.com\r\n"
15357 "Proxy-Connection: keep-alive\r\n\r\n"),
15358 };
[email protected]8c405132011-01-11 22:03:1815359
David Benjamin3b94b0f2019-04-25 23:07:5215360 // When the server rejects the client certificate, it will close the
15361 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
15362 // TLS 1.2 with False Start), the error is returned out of the first Read().
15363 for (bool reject_in_connect : {true, false}) {
15364 SCOPED_TRACE(reject_in_connect);
15365 // Client certificate errors are typically signaled with
15366 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
15367 // protocol error.
15368 for (Error reject_error :
15369 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
15370 SCOPED_TRACE(reject_error);
15371 // Tunneled and non-tunneled requests are handled differently. Test both.
15372 for (const HttpRequestInfo& request : requests) {
15373 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1815374
David Benjamin3b94b0f2019-04-25 23:07:5215375 session_deps_.socket_factory =
15376 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1815377
David Benjamin3b94b0f2019-04-25 23:07:5215378 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
15379 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
15380 // for proxies. Rather than represending the endpoint
15381 // (www.example.com:443), they represent failures with the HTTPS proxy
15382 // (proxy:70).
15383 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
15384 ssl_data1.cert_request_info = cert_request.get();
15385 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15386 StaticSocketDataProvider data1;
15387 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1815388
David Benjamin3b94b0f2019-04-25 23:07:5215389 base::Optional<SSLSocketDataProvider> ssl_data2;
15390 base::Optional<StaticSocketDataProvider> data2;
15391 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
15392 if (reject_in_connect) {
15393 ssl_data2.emplace(ASYNC, reject_error);
15394 // There are no reads or writes.
15395 data2.emplace();
15396 } else {
15397 ssl_data2.emplace(ASYNC, OK);
15398 // We will get one Write() in before observing the error in Read().
15399 if (request.url.SchemeIsCryptographic()) {
15400 data2.emplace(error_in_read, https_writes);
15401 } else {
15402 data2.emplace(error_in_read, http_writes);
15403 }
15404 }
15405 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1815406
David Benjamin3b94b0f2019-04-25 23:07:5215407 session_deps_.socket_factory->AddSSLSocketDataProvider(
15408 &ssl_data2.value());
15409 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1815410
David Benjamin3b94b0f2019-04-25 23:07:5215411 std::unique_ptr<HttpNetworkSession> session =
15412 CreateSession(&session_deps_);
15413 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15414
15415 // Begin the SSL handshake with the proxy.
15416 TestCompletionCallback callback;
15417 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15418 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15419
15420 // Complete the SSL handshake, which should abort due to requiring a
15421 // client certificate.
15422 rv = callback.WaitForResult();
15423 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15424
15425 // Indicate that no certificate should be supplied. From the
15426 // perspective of SSLClientCertCache, NULL is just as meaningful as a
15427 // real certificate, so this is the same as supply a
15428 // legitimate-but-unacceptable certificate.
15429 rv =
15430 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
15431 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15432
15433 // Ensure the certificate was added to the client auth cache before
15434 // allowing the connection to continue restarting.
15435 scoped_refptr<X509Certificate> client_cert;
15436 scoped_refptr<SSLPrivateKey> client_private_key;
15437 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
15438 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15439 ASSERT_FALSE(client_cert);
15440 // Ensure the certificate was NOT cached for the endpoint. This only
15441 // applies to HTTPS requests, but is fine to check for HTTP requests.
15442 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15443 HostPortPair("www.example.com", 443), &client_cert,
15444 &client_private_key));
15445
15446 // Restart the handshake. This will consume ssl_data2. The result code
15447 // is checked against what ssl_data2 should return.
15448 rv = callback.WaitForResult();
15449 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
15450 IsError(reject_error)));
15451
15452 // Now that the new handshake has failed, ensure that the client
15453 // certificate was removed from the client auth cache.
15454 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15455 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15456 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15457 HostPortPair("www.example.com", 443), &client_cert,
15458 &client_private_key));
15459 }
15460 }
[email protected]8c405132011-01-11 22:03:1815461 }
15462}
15463
David Benjamin1a0566082019-04-30 07:36:1915464// Test that HttpNetworkTransaction correctly handles (mocked) certificate
15465// requests during a TLS renegotiation.
15466TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
15467 HttpRequestInfo request_info;
15468 request_info.url = GURL("https://www.example.com/");
15469 request_info.method = "GET";
15470 request_info.load_flags = LOAD_NORMAL;
15471 request_info.traffic_annotation =
15472 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15473
15474 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
15475 cert_request->host_and_port = HostPortPair("www.example.com", 443);
15476
15477 std::unique_ptr<FakeClientCertIdentity> identity =
15478 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
15479 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
15480 ASSERT_TRUE(identity);
15481
15482 // The first connection's handshake succeeds, but we get
15483 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
15484 SSLSocketDataProvider ssl_data1(ASYNC, OK);
15485 ssl_data1.cert_request_info = cert_request.get();
15486 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15487 MockWrite data1_writes[] = {
15488 MockWrite("GET / HTTP/1.1\r\n"
15489 "Host: www.example.com\r\n"
15490 "Connection: keep-alive\r\n\r\n"),
15491 };
15492 MockRead data1_reads[] = {
15493 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
15494 };
15495 StaticSocketDataProvider data1(data1_reads, data1_writes);
15496 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15497
15498 // After supplying with certificate, we restart the request from the top,
15499 // which succeeds this time.
15500 SSLSocketDataProvider ssl_data2(ASYNC, OK);
15501 ssl_data2.expected_send_client_cert = true;
15502 ssl_data2.expected_client_cert = identity->certificate();
15503 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
15504 MockWrite data2_writes[] = {
15505 MockWrite("GET / HTTP/1.1\r\n"
15506 "Host: www.example.com\r\n"
15507 "Connection: keep-alive\r\n\r\n"),
15508 };
15509 MockRead data2_reads[] = {
15510 MockRead("HTTP/1.1 200 OK\r\n"
15511 "Content-Length: 0\r\n\r\n"),
15512 };
15513 StaticSocketDataProvider data2(data2_reads, data2_writes);
15514 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15515
15516 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
15517 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15518
15519 TestCompletionCallback callback;
15520 int rv = callback.GetResult(
15521 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
15522 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15523
15524 rv = trans.RestartWithCertificate(identity->certificate(),
15525 identity->ssl_private_key(),
15526 callback.callback());
15527 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15528
15529 // Ensure the certificate was added to the client auth cache
15530 // allowing the connection to continue restarting.
15531 scoped_refptr<X509Certificate> client_cert;
15532 scoped_refptr<SSLPrivateKey> client_private_key;
15533 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
15534 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15535 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15536
15537 // Complete the handshake. The request now succeeds.
15538 rv = callback.WaitForResult();
15539 ASSERT_THAT(rv, IsError(OK));
15540 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
15541
15542 // The client certificate remains in the cache.
15543 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
15544 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15545 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15546}
15547
bncd16676a2016-07-20 16:23:0115548TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4615549 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915550 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915551 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615552
bnc032658ba2016-09-26 18:17:1515553 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615554
Ryan Hamilton0239aac2018-05-19 00:03:1315555 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915556 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815557 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315558 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715559 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615560 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115561 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615562 };
Ryan Hamilton0239aac2018-05-19 00:03:1315563 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515564 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315565 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115566 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315567 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515568 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315569 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115570 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615571 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115572 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15573 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315574 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615575 };
15576
eroman36d84e54432016-03-17 03:23:0215577 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215578 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115579 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715580 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615581
[email protected]aa22b242011-11-16 18:58:2915582 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615583 HttpRequestInfo request1;
15584 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315585 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615586 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015587 request1.traffic_annotation =
15588 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015589 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615590
tfarina42834112016-09-22 13:38:2015591 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115592 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15593 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615594
15595 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215596 ASSERT_TRUE(response);
15597 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215598 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615599
15600 std::string response_data;
robpercival214763f2016-07-01 23:27:0115601 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615602 EXPECT_EQ("hello!", response_data);
15603
bnca4d611d2016-09-22 19:55:3715604 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315605 rv = session_deps_.host_resolver->LoadIntoCache(
15606 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0115607 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4615608
15609 HttpRequestInfo request2;
15610 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715611 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4615612 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015613 request2.traffic_annotation =
15614 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015615 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615616
tfarina42834112016-09-22 13:38:2015617 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115618 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15619 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615620
15621 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215622 ASSERT_TRUE(response);
15623 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215624 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615625 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215626 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115627 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615628 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4615629}
15630
bncd16676a2016-07-20 16:23:0115631TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0215632 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915633 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915634 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0215635
bnc032658ba2016-09-26 18:17:1515636 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0215637
Ryan Hamilton0239aac2018-05-19 00:03:1315638 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915639 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815640 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315641 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715642 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0215643 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115644 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0215645 };
Ryan Hamilton0239aac2018-05-19 00:03:1315646 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515647 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315648 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115649 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315650 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515651 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315652 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115653 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0215654 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115655 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15656 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315657 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0215658 };
15659
eroman36d84e54432016-03-17 03:23:0215660 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215661 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115662 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715663 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0215664
15665 TestCompletionCallback callback;
15666 HttpRequestInfo request1;
15667 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315668 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0215669 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015670 request1.traffic_annotation =
15671 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015672 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215673
tfarina42834112016-09-22 13:38:2015674 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115675 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15676 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215677
15678 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215679 ASSERT_TRUE(response);
15680 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215681 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215682
15683 std::string response_data;
robpercival214763f2016-07-01 23:27:0115684 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215685 EXPECT_EQ("hello!", response_data);
15686
15687 HttpRequestInfo request2;
15688 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715689 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0215690 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015691 request2.traffic_annotation =
15692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015693 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215694
tfarina42834112016-09-22 13:38:2015695 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115696 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15697 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215698
15699 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215700 ASSERT_TRUE(response);
15701 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215702 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215703 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215704 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115705 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215706 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0215707}
15708
bnc8016c1f2017-03-31 02:11:2915709// Regression test for https://crbug.com/546991.
15710// The server might not be able to serve an IP pooled request, and might send a
15711// 421 Misdirected Request response status to indicate this.
15712// HttpNetworkTransaction should reset the request and retry without IP pooling.
15713TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
15714 // Two hosts resolve to the same IP address.
15715 const std::string ip_addr = "1.2.3.4";
15716 IPAddress ip;
15717 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15718 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15719
Jeremy Roman0579ed62017-08-29 15:56:1915720 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2915721 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15722 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15723
15724 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15725
15726 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315727 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2915728 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15729 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315730 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2915731 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315732 spdy::SpdySerializedFrame rst(
15733 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2915734 MockWrite writes1[] = {
15735 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15736 CreateMockWrite(rst, 6),
15737 };
15738
15739 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315740 spdy::SpdySerializedFrame resp1(
15741 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15742 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15743 spdy::SpdyHeaderBlock response_headers;
15744 response_headers[spdy::kHttp2StatusHeader] = "421";
15745 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2915746 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
15747 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15748 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15749
15750 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115751 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2915752 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15753
15754 AddSSLSocketData();
15755
15756 // Retry the second request on a second connection.
15757 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315758 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2915759 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15760 MockWrite writes2[] = {
15761 CreateMockWrite(req3, 0),
15762 };
15763
Ryan Hamilton0239aac2018-05-19 00:03:1315764 spdy::SpdySerializedFrame resp3(
15765 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
15766 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2915767 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15768 MockRead(ASYNC, 0, 3)};
15769
15770 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115771 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2915772 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15773
15774 AddSSLSocketData();
15775
15776 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315777 int rv = session_deps_.host_resolver->LoadIntoCache(
15778 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2915779 EXPECT_THAT(rv, IsOk());
15780
15781 HttpRequestInfo request1;
15782 request1.method = "GET";
15783 request1.url = GURL("https://www.example.org/");
15784 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015785 request1.traffic_annotation =
15786 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915787 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15788
Eric Orthf4db66a2019-02-19 21:35:3315789 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2915790 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15791 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15792 rv = callback.WaitForResult();
15793 EXPECT_THAT(rv, IsOk());
15794
15795 const HttpResponseInfo* response = trans1.GetResponseInfo();
15796 ASSERT_TRUE(response);
15797 ASSERT_TRUE(response->headers);
15798 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15799 EXPECT_TRUE(response->was_fetched_via_spdy);
15800 EXPECT_TRUE(response->was_alpn_negotiated);
15801 std::string response_data;
15802 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
15803 EXPECT_EQ("hello!", response_data);
15804
15805 HttpRequestInfo request2;
15806 request2.method = "GET";
15807 request2.url = GURL("https://mail.example.org/");
15808 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015809 request2.traffic_annotation =
15810 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915811 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
15812
15813 BoundTestNetLog log;
15814 rv = trans2.Start(&request2, callback.callback(), log.bound());
15815 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15816 rv = callback.WaitForResult();
15817 EXPECT_THAT(rv, IsOk());
15818
15819 response = trans2.GetResponseInfo();
15820 ASSERT_TRUE(response);
15821 ASSERT_TRUE(response->headers);
15822 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15823 EXPECT_TRUE(response->was_fetched_via_spdy);
15824 EXPECT_TRUE(response->was_alpn_negotiated);
15825 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
15826 EXPECT_EQ("hello!", response_data);
15827
15828 TestNetLogEntry::List entries;
15829 log.GetEntries(&entries);
davidbence688ae2017-05-04 15:12:5915830 ExpectLogContainsSomewhere(
15831 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2915832 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5915833}
15834
15835// Test that HTTP 421 responses are properly returned to the caller if received
15836// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
15837// portions of the response.
15838TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
15839 // Two hosts resolve to the same IP address.
15840 const std::string ip_addr = "1.2.3.4";
15841 IPAddress ip;
15842 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15843 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15844
Jeremy Roman0579ed62017-08-29 15:56:1915845 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5915846 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15847 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15848
15849 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15850
15851 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315852 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5915853 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15854 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315855 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5915856 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315857 spdy::SpdySerializedFrame rst(
15858 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5915859 MockWrite writes1[] = {
15860 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15861 CreateMockWrite(rst, 6),
15862 };
15863
15864 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315865 spdy::SpdySerializedFrame resp1(
15866 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15867 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15868 spdy::SpdyHeaderBlock response_headers;
15869 response_headers[spdy::kHttp2StatusHeader] = "421";
15870 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5915871 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
15872 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15873 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15874
15875 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115876 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5915877 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15878
15879 AddSSLSocketData();
15880
15881 // Retry the second request on a second connection. It returns 421 Misdirected
15882 // Retry again.
15883 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315884 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5915885 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15886 MockWrite writes2[] = {
15887 CreateMockWrite(req3, 0),
15888 };
15889
Ryan Hamilton0239aac2018-05-19 00:03:1315890 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5915891 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1315892 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5915893 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15894 MockRead(ASYNC, 0, 3)};
15895
15896 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115897 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5915898 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15899
15900 AddSSLSocketData();
15901
15902 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315903 int rv = session_deps_.host_resolver->LoadIntoCache(
15904 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5915905 EXPECT_THAT(rv, IsOk());
15906
15907 HttpRequestInfo request1;
15908 request1.method = "GET";
15909 request1.url = GURL("https://www.example.org/");
15910 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015911 request1.traffic_annotation =
15912 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5915913 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15914
Eric Orthf4db66a2019-02-19 21:35:3315915 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5915916 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15917 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15918 rv = callback.WaitForResult();
15919 EXPECT_THAT(rv, IsOk());
15920
15921 const HttpResponseInfo* response = trans1.GetResponseInfo();
15922 ASSERT_TRUE(response);
15923 ASSERT_TRUE(response->headers);
15924 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15925 EXPECT_TRUE(response->was_fetched_via_spdy);
15926 EXPECT_TRUE(response->was_alpn_negotiated);
15927 std::string response_data;
15928 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
15929 EXPECT_EQ("hello!", response_data);
15930
15931 HttpRequestInfo request2;
15932 request2.method = "GET";
15933 request2.url = GURL("https://mail.example.org/");
15934 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015935 request2.traffic_annotation =
15936 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5915937 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
15938
15939 BoundTestNetLog log;
15940 rv = trans2.Start(&request2, callback.callback(), log.bound());
15941 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15942 rv = callback.WaitForResult();
15943 EXPECT_THAT(rv, IsOk());
15944
15945 // After a retry, the 421 Misdirected Request is reported back up to the
15946 // caller.
15947 response = trans2.GetResponseInfo();
15948 ASSERT_TRUE(response);
15949 ASSERT_TRUE(response->headers);
15950 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
15951 EXPECT_TRUE(response->was_fetched_via_spdy);
15952 EXPECT_TRUE(response->was_alpn_negotiated);
15953 EXPECT_TRUE(response->ssl_info.cert);
15954 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
15955 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2915956}
15957
bncd16676a2016-07-20 16:23:0115958TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1315959 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3415960 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
15961 session_deps_.host_resolver =
15962 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0915963 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615964
bnc032658ba2016-09-26 18:17:1515965 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615966
Ryan Hamilton0239aac2018-05-19 00:03:1315967 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915968 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815969 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315970 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715971 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615972 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115973 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615974 };
Ryan Hamilton0239aac2018-05-19 00:03:1315975 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515976 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315977 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115978 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315979 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515980 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315981 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115982 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615983 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115984 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15985 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315986 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615987 };
15988
eroman36d84e54432016-03-17 03:23:0215989 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215990 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115991 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715992 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615993
[email protected]aa22b242011-11-16 18:58:2915994 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615995 HttpRequestInfo request1;
15996 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315997 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615998 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1015999 request1.traffic_annotation =
16000 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016001 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616002
tfarina42834112016-09-22 13:38:2016003 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116004 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16005 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616006
16007 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216008 ASSERT_TRUE(response);
16009 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216010 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616011
16012 std::string response_data;
robpercival214763f2016-07-01 23:27:0116013 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616014 EXPECT_EQ("hello!", response_data);
16015
16016 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3316017 rv = session_deps_.host_resolver->LoadIntoCache(
16018 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116019 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616020
16021 HttpRequestInfo request2;
16022 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716023 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616024 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016025 request2.traffic_annotation =
16026 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016027 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616028
tfarina42834112016-09-22 13:38:2016029 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116030 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16031 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616032
16033 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216034 ASSERT_TRUE(response);
16035 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216036 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616037 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216038 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116039 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616040 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616041}
16042
bncd16676a2016-07-20 16:23:0116043TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2316044 const std::string https_url = "https://www.example.org:8080/";
16045 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416046
16047 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1316048 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916049 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0416050
16051 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116052 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0416053 };
16054
Raul Tambre94493c652019-03-11 17:18:3516055 spdy::SpdySerializedFrame resp1(
16056 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316057 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116058 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5916059 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0416060
Ryan Sleevib8d7ea02018-05-07 20:01:0116061 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416062 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716063 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416064
16065 // HTTP GET for the HTTP URL
16066 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1316067 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3416068 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2316069 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3416070 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0416071 };
16072
16073 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1316074 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
16075 MockRead(ASYNC, 2, "hello"),
16076 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0416077 };
16078
Ryan Sleevib8d7ea02018-05-07 20:01:0116079 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0416080
[email protected]8450d722012-07-02 19:14:0416081 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616082 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716083 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16084 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16085 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0416086
danakj1fd259a02016-04-16 03:17:0916087 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0416088
16089 // Start the first transaction to set up the SpdySession
16090 HttpRequestInfo request1;
16091 request1.method = "GET";
16092 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416093 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016094 request1.traffic_annotation =
16095 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016096 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416097 TestCompletionCallback callback1;
16098 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016099 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516100 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416101
robpercival214763f2016-07-01 23:27:0116102 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416103 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16104
16105 // Now, start the HTTP request
16106 HttpRequestInfo request2;
16107 request2.method = "GET";
16108 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416109 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016110 request2.traffic_annotation =
16111 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016112 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416113 TestCompletionCallback callback2;
16114 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016115 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516116 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416117
robpercival214763f2016-07-01 23:27:0116118 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416119 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16120}
16121
bnc5452e2a2015-05-08 16:27:4216122// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
16123// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0116124TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2516125 url::SchemeHostPort server("https", "www.example.org", 443);
16126 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4216127
bnc8bef8da22016-05-30 01:28:2516128 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4216129 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616130 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216131 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16132
16133 // No data should be read from the alternative, because HTTP/1.1 is
16134 // negotiated.
16135 StaticSocketDataProvider data;
16136 session_deps_.socket_factory->AddSocketDataProvider(&data);
16137
16138 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4616139 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4216140 // mocked. This way the request relies on the alternate Job.
16141 StaticSocketDataProvider data_refused;
16142 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16143 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16144
zhongyi3d4a55e72016-04-22 20:36:4616145 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916146 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016147 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216148 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116149 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216150 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116151 http_server_properties->SetHttp2AlternativeService(
16152 server, alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216153
bnc5452e2a2015-05-08 16:27:4216154 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4616155 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216156 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2516157 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e2018-02-07 07:41:1016158 request.traffic_annotation =
16159 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216160 TestCompletionCallback callback;
16161
16162 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5216163 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2016164 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5216165 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4216166}
16167
bnc40448a532015-05-11 19:13:1416168// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4616169// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1416170// succeeds, the request should succeed, even if the latter fails because
16171// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0116172TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2516173 url::SchemeHostPort server("https", "www.example.org", 443);
16174 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1416175
16176 // Negotiate HTTP/1.1 with alternative.
16177 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616178 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416179 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
16180
16181 // No data should be read from the alternative, because HTTP/1.1 is
16182 // negotiated.
16183 StaticSocketDataProvider data;
16184 session_deps_.socket_factory->AddSocketDataProvider(&data);
16185
zhongyi3d4a55e72016-04-22 20:36:4616186 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1416187 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616188 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416189 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
16190
16191 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2516192 MockWrite("GET / HTTP/1.1\r\n"
16193 "Host: www.example.org\r\n"
16194 "Connection: keep-alive\r\n\r\n"),
16195 MockWrite("GET /second HTTP/1.1\r\n"
16196 "Host: www.example.org\r\n"
16197 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1416198 };
16199
16200 MockRead http_reads[] = {
16201 MockRead("HTTP/1.1 200 OK\r\n"),
16202 MockRead("Content-Type: text/html\r\n"),
16203 MockRead("Content-Length: 6\r\n\r\n"),
16204 MockRead("foobar"),
16205 MockRead("HTTP/1.1 200 OK\r\n"),
16206 MockRead("Content-Type: text/html\r\n"),
16207 MockRead("Content-Length: 7\r\n\r\n"),
16208 MockRead("another"),
16209 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116210 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1416211 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16212
zhongyi3d4a55e72016-04-22 20:36:4616213 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916214 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016215 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1416216 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116217 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216218 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116219 http_server_properties->SetHttp2AlternativeService(
16220 server, alternative_service, expiration);
bnc40448a532015-05-11 19:13:1416221
16222 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16223 HttpRequestInfo request1;
16224 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2516225 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1416226 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016227 request1.traffic_annotation =
16228 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416229 TestCompletionCallback callback1;
16230
tfarina42834112016-09-22 13:38:2016231 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416232 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116233 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416234
16235 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216236 ASSERT_TRUE(response1);
16237 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1416238 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
16239
16240 std::string response_data1;
robpercival214763f2016-07-01 23:27:0116241 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1416242 EXPECT_EQ("foobar", response_data1);
16243
16244 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
16245 // for alternative service.
16246 EXPECT_TRUE(
16247 http_server_properties->IsAlternativeServiceBroken(alternative_service));
16248
zhongyi3d4a55e72016-04-22 20:36:4616249 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1416250 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4616251 // to server.
bnc40448a532015-05-11 19:13:1416252 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16253 HttpRequestInfo request2;
16254 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2516255 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1416256 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016257 request2.traffic_annotation =
16258 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416259 TestCompletionCallback callback2;
16260
tfarina42834112016-09-22 13:38:2016261 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416262 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116263 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416264
16265 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216266 ASSERT_TRUE(response2);
16267 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1416268 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
16269
16270 std::string response_data2;
robpercival214763f2016-07-01 23:27:0116271 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1416272 EXPECT_EQ("another", response_data2);
16273}
16274
bnc5452e2a2015-05-08 16:27:4216275// Alternative service requires HTTP/2 (or SPDY), but there is already a
16276// HTTP/1.1 socket open to the alternative server. That socket should not be
16277// used.
bncd16676a2016-07-20 16:23:0116278TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4616279 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4216280 HostPortPair alternative("alternative.example.org", 443);
16281 std::string origin_url = "https://origin.example.org:443";
16282 std::string alternative_url = "https://alternative.example.org:443";
16283
16284 // Negotiate HTTP/1.1 with alternative.example.org.
16285 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616286 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216287 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16288
16289 // HTTP/1.1 data for |request1| and |request2|.
16290 MockWrite http_writes[] = {
16291 MockWrite(
16292 "GET / HTTP/1.1\r\n"
16293 "Host: alternative.example.org\r\n"
16294 "Connection: keep-alive\r\n\r\n"),
16295 MockWrite(
16296 "GET / HTTP/1.1\r\n"
16297 "Host: alternative.example.org\r\n"
16298 "Connection: keep-alive\r\n\r\n"),
16299 };
16300
16301 MockRead http_reads[] = {
16302 MockRead(
16303 "HTTP/1.1 200 OK\r\n"
16304 "Content-Type: text/html; charset=iso-8859-1\r\n"
16305 "Content-Length: 40\r\n\r\n"
16306 "first HTTP/1.1 response from alternative"),
16307 MockRead(
16308 "HTTP/1.1 200 OK\r\n"
16309 "Content-Type: text/html; charset=iso-8859-1\r\n"
16310 "Content-Length: 41\r\n\r\n"
16311 "second HTTP/1.1 response from alternative"),
16312 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116313 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4216314 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16315
16316 // This test documents that an alternate Job should not pool to an already
16317 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4616318 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4216319 StaticSocketDataProvider data_refused;
16320 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16321 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16322
zhongyi3d4a55e72016-04-22 20:36:4616323 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916324 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016325 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216326 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116327 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216328 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116329 http_server_properties->SetHttp2AlternativeService(
16330 server, alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216331
16332 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4216333 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4616334 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216335 request1.method = "GET";
16336 request1.url = GURL(alternative_url);
16337 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016338 request1.traffic_annotation =
16339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216340 TestCompletionCallback callback1;
16341
tfarina42834112016-09-22 13:38:2016342 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116343 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616344 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216345 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5216346 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4216347 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216348 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216349 EXPECT_FALSE(response1->was_fetched_via_spdy);
16350 std::string response_data1;
bnc691fda62016-08-12 00:43:1616351 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4216352 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
16353
16354 // Request for origin.example.org, which has an alternative service. This
16355 // will start two Jobs: the alternative looks for connections to pool to,
16356 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4616357 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4216358 // this request fails.
bnc5452e2a2015-05-08 16:27:4216359 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4616360 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216361 request2.method = "GET";
16362 request2.url = GURL(origin_url);
16363 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016364 request2.traffic_annotation =
16365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216366 TestCompletionCallback callback2;
16367
tfarina42834112016-09-22 13:38:2016368 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116369 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4216370
16371 // Another transaction to alternative. This is to test that the HTTP/1.1
16372 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4216373 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4616374 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216375 request3.method = "GET";
16376 request3.url = GURL(alternative_url);
16377 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016378 request3.traffic_annotation =
16379 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216380 TestCompletionCallback callback3;
16381
tfarina42834112016-09-22 13:38:2016382 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116383 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616384 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216385 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5216386 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4216387 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216388 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216389 EXPECT_FALSE(response3->was_fetched_via_spdy);
16390 std::string response_data3;
bnc691fda62016-08-12 00:43:1616391 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4216392 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
16393}
16394
bncd16676a2016-07-20 16:23:0116395TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2316396 const std::string https_url = "https://www.example.org:8080/";
16397 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416398
rdsmithebb50aa2015-11-12 03:44:3816399 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0116400 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3816401
[email protected]8450d722012-07-02 19:14:0416402 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2316403 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0416404 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
16405 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
16406 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1316407 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916408 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316409 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0216410 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3916411
16412 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1316413 spdy::SpdyHeaderBlock req2_block;
16414 req2_block[spdy::kHttp2MethodHeader] = "GET";
16415 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
16416 req2_block[spdy::kHttp2SchemeHeader] = "http";
16417 req2_block[spdy::kHttp2PathHeader] = "/";
16418 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1516419 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0416420
16421 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116422 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
16423 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0416424 };
16425
Ryan Hamilton0239aac2018-05-19 00:03:1316426 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1516427 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316428 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1516429 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316430 spdy::SpdySerializedFrame body1(
16431 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
16432 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3816433 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316434 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3816435 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3516436 spdy::SpdySerializedFrame resp2(
16437 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316438 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3316439 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116440 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3316441 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4116442 CreateMockRead(wrapped_resp1, 4),
16443 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3316444 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4116445 CreateMockRead(resp2, 8),
16446 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3316447 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
16448 };
[email protected]8450d722012-07-02 19:14:0416449
Ryan Sleevib8d7ea02018-05-07 20:01:0116450 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416451 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716452 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416453
Lily Houghton8c2f97d2018-01-22 05:06:5916454 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4916455 ProxyResolutionService::CreateFixedFromPacResult(
16456 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116457 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716458 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0416459 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616460 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0416462 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616463 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316464 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16465 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0416466
danakj1fd259a02016-04-16 03:17:0916467 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0416468
16469 // Start the first transaction to set up the SpdySession
16470 HttpRequestInfo request1;
16471 request1.method = "GET";
16472 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416473 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016474 request1.traffic_annotation =
16475 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016476 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416477 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2016478 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416479
mmenke666a6fea2015-12-19 04:16:3316480 // This pause is a hack to avoid running into https://crbug.com/497228.
16481 data1.RunUntilPaused();
16482 base::RunLoop().RunUntilIdle();
16483 data1.Resume();
robpercival214763f2016-07-01 23:27:0116484 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0416485 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16486
[email protected]f6c63db52013-02-02 00:35:2216487 LoadTimingInfo load_timing_info1;
16488 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
16489 TestLoadTimingNotReusedWithPac(load_timing_info1,
16490 CONNECT_TIMING_HAS_SSL_TIMES);
16491
mmenke666a6fea2015-12-19 04:16:3316492 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0416493 HttpRequestInfo request2;
16494 request2.method = "GET";
16495 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416496 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016497 request2.traffic_annotation =
16498 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016499 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416500 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2016501 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416502
mmenke666a6fea2015-12-19 04:16:3316503 // This pause is a hack to avoid running into https://crbug.com/497228.
16504 data1.RunUntilPaused();
16505 base::RunLoop().RunUntilIdle();
16506 data1.Resume();
robpercival214763f2016-07-01 23:27:0116507 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3316508
[email protected]8450d722012-07-02 19:14:0416509 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2216510
16511 LoadTimingInfo load_timing_info2;
16512 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
16513 // The established SPDY sessions is considered reused by the HTTP request.
16514 TestLoadTimingReusedWithPac(load_timing_info2);
16515 // HTTP requests over a SPDY session should have a different connection
16516 // socket_log_id than requests over a tunnel.
16517 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0416518}
16519
[email protected]2d88e7d2012-07-19 17:55:1716520// Test that in the case where we have a SPDY session to a SPDY proxy
16521// that we do not pool other origins that resolve to the same IP when
16522// the certificate does not match the new origin.
16523// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0116524TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2316525 const std::string url1 = "http://www.example.org/";
16526 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1716527 const std::string ip_addr = "1.2.3.4";
16528
rdsmithebb50aa2015-11-12 03:44:3816529 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0116530 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3816531
[email protected]2d88e7d2012-07-19 17:55:1716532 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1316533 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2316534 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1316535 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1516536 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1716537
16538 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116539 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1716540 };
16541
Raul Tambre94493c652019-03-11 17:18:3516542 spdy::SpdySerializedFrame resp1(
16543 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316544 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1716545 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116546 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
16547 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1716548 };
16549
Ryan Sleevib8d7ea02018-05-07 20:01:0116550 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3216551 IPAddress ip;
martijn654c8c42016-02-10 22:10:5916552 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1716553 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16554 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3316555 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1716556
16557 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1316558 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916559 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1716560
16561 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116562 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1716563 };
16564
Ryan Hamilton0239aac2018-05-19 00:03:1316565 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3516566 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316567 spdy::SpdySerializedFrame body2(
16568 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116569 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3316570 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1716571
Ryan Sleevib8d7ea02018-05-07 20:01:0116572 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1716573 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3316574 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1716575
16576 // Set up a proxy config that sends HTTP requests to a proxy, and
16577 // all others direct.
16578 ProxyConfig proxy_config;
16579 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4916580 session_deps_.proxy_resolution_service =
16581 std::make_unique<ProxyResolutionService>(
16582 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
16583 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
16584 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1716585
bncce36dca22015-04-21 22:11:2316586 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616587 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1716588 // Load a valid cert. Note, that this does not need to
16589 // be valid for proxy because the MockSSLClientSocket does
16590 // not actually verify it. But SpdySession will use this
16591 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4916592 ssl1.ssl_info.cert =
16593 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
16594 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3316595 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16596 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1716597
16598 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616599 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16601 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1716602
Jeremy Roman0579ed62017-08-29 15:56:1916603 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2316604 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0716605 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1716606
danakj1fd259a02016-04-16 03:17:0916607 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1716608
16609 // Start the first transaction to set up the SpdySession
16610 HttpRequestInfo request1;
16611 request1.method = "GET";
16612 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1716613 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016614 request1.traffic_annotation =
16615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016616 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716617 TestCompletionCallback callback1;
16618 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016619 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3316620 // This pause is a hack to avoid running into https://crbug.com/497228.
16621 data1.RunUntilPaused();
16622 base::RunLoop().RunUntilIdle();
16623 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1716624
robpercival214763f2016-07-01 23:27:0116625 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716626 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16627
16628 // Now, start the HTTP request
16629 HttpRequestInfo request2;
16630 request2.method = "GET";
16631 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1716632 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016633 request2.traffic_annotation =
16634 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016635 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716636 TestCompletionCallback callback2;
16637 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016638 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516639 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1716640
16641 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0116642 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716643 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16644}
16645
[email protected]85f97342013-04-17 06:12:2416646// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
16647// error) in SPDY session, removes the socket from pool and closes the SPDY
16648// session. Verify that new url's from the same HttpNetworkSession (and a new
16649// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0116650TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2316651 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2416652
16653 MockRead reads1[] = {
16654 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
16655 };
16656
Ryan Sleevib8d7ea02018-05-07 20:01:0116657 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2416658
Ryan Hamilton0239aac2018-05-19 00:03:1316659 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916660 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2416661 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116662 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2416663 };
16664
Raul Tambre94493c652019-03-11 17:18:3516665 spdy::SpdySerializedFrame resp2(
16666 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316667 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2416668 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4116669 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
16670 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2416671 };
16672
Ryan Sleevib8d7ea02018-05-07 20:01:0116673 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2416674
[email protected]85f97342013-04-17 06:12:2416675 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616676 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016677 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16678 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2416679
16680 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616681 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016682 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16683 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2416684
danakj1fd259a02016-04-16 03:17:0916685 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5016686 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2416687
16688 // Start the first transaction to set up the SpdySession and verify that
16689 // connection was closed.
16690 HttpRequestInfo request1;
16691 request1.method = "GET";
16692 request1.url = GURL(https_url);
16693 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016694 request1.traffic_annotation =
16695 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016696 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416697 TestCompletionCallback callback1;
16698 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016699 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0116700 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2416701
16702 // Now, start the second request and make sure it succeeds.
16703 HttpRequestInfo request2;
16704 request2.method = "GET";
16705 request2.url = GURL(https_url);
16706 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016707 request2.traffic_annotation =
16708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016709 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416710 TestCompletionCallback callback2;
16711 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016712 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2416713
robpercival214763f2016-07-01 23:27:0116714 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2416715 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16716}
16717
bncd16676a2016-07-20 16:23:0116718TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0316719 ClientSocketPoolManager::set_max_sockets_per_group(
16720 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16721 ClientSocketPoolManager::set_max_sockets_per_pool(
16722 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16723
16724 // Use two different hosts with different IPs so they don't get pooled.
16725 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
16726 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0916727 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0316728
16729 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616730 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316731 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616732 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16734 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16735
Ryan Hamilton0239aac2018-05-19 00:03:1316736 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916737 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316738 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116739 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0316740 };
Ryan Hamilton0239aac2018-05-19 00:03:1316741 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516742 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316743 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116744 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316745 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116746 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916747 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316748 };
16749
rdsmithebb50aa2015-11-12 03:44:3816750 // Use a separate test instance for the separate SpdySession that will be
16751 // created.
bncd16676a2016-07-20 16:23:0116752 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0116753 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1216754 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0316755
Ryan Hamilton0239aac2018-05-19 00:03:1316756 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4916757 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316758 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116759 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0316760 };
Ryan Hamilton0239aac2018-05-19 00:03:1316761 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516762 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316763 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116764 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316765 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116766 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916767 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316768 };
16769
Ryan Sleevib8d7ea02018-05-07 20:01:0116770 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1216771 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0316772
16773 MockWrite http_write[] = {
16774 MockWrite("GET / HTTP/1.1\r\n"
16775 "Host: www.a.com\r\n"
16776 "Connection: keep-alive\r\n\r\n"),
16777 };
16778
16779 MockRead http_read[] = {
16780 MockRead("HTTP/1.1 200 OK\r\n"),
16781 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16782 MockRead("Content-Length: 6\r\n\r\n"),
16783 MockRead("hello!"),
16784 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116785 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0316786 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16787
16788 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116789 SpdySessionKey spdy_session_key_a(
16790 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16791 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316792 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616793 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316794
16795 TestCompletionCallback callback;
16796 HttpRequestInfo request1;
16797 request1.method = "GET";
16798 request1.url = GURL("https://www.a.com/");
16799 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016800 request1.traffic_annotation =
16801 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816802 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1916803 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316804
tfarina42834112016-09-22 13:38:2016805 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116806 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16807 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316808
16809 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216810 ASSERT_TRUE(response);
16811 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216812 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316813 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216814 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0316815
16816 std::string response_data;
robpercival214763f2016-07-01 23:27:0116817 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316818 EXPECT_EQ("hello!", response_data);
16819 trans.reset();
16820 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616821 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316822
16823 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116824 SpdySessionKey spdy_session_key_b(
16825 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16826 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316827 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616828 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316829 HttpRequestInfo request2;
16830 request2.method = "GET";
16831 request2.url = GURL("https://www.b.com/");
16832 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016833 request2.traffic_annotation =
16834 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816835 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916836 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316837
tfarina42834112016-09-22 13:38:2016838 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116839 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16840 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316841
16842 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216843 ASSERT_TRUE(response);
16844 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216845 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316846 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216847 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116848 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316849 EXPECT_EQ("hello!", response_data);
16850 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616851 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316852 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616853 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316854
16855 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1116856 SpdySessionKey spdy_session_key_a1(
16857 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16858 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316859 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616860 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0316861 HttpRequestInfo request3;
16862 request3.method = "GET";
16863 request3.url = GURL("http://www.a.com/");
16864 request3.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1016865 request3.traffic_annotation =
16866 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816867 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916868 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316869
tfarina42834112016-09-22 13:38:2016870 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116871 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16872 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316873
16874 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216875 ASSERT_TRUE(response);
16876 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0316877 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16878 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216879 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116880 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316881 EXPECT_EQ("hello!", response_data);
16882 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616883 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316884 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616885 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316886}
16887
bncd16676a2016-07-20 16:23:0116888TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0416889 HttpRequestInfo request;
16890 request.method = "GET";
bncce36dca22015-04-21 22:11:2316891 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016892 request.traffic_annotation =
16893 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416894
danakj1fd259a02016-04-16 03:17:0916895 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616896 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416897
ttuttled9dbc652015-09-29 20:00:5916898 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0416899 StaticSocketDataProvider data;
16900 data.set_connect_data(mock_connect);
16901 session_deps_.socket_factory->AddSocketDataProvider(&data);
16902
16903 TestCompletionCallback callback;
16904
tfarina42834112016-09-22 13:38:2016905 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116906 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416907
16908 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116909 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0416910
[email protected]79e1fd62013-06-20 06:50:0416911 // We don't care whether this succeeds or fails, but it shouldn't crash.
16912 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616913 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4716914
16915 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1616916 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4716917 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0116918 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5916919
16920 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1616921 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5916922 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0416923}
16924
bncd16676a2016-07-20 16:23:0116925TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0416926 HttpRequestInfo request;
16927 request.method = "GET";
bncce36dca22015-04-21 22:11:2316928 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016929 request.traffic_annotation =
16930 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416931
danakj1fd259a02016-04-16 03:17:0916932 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616933 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416934
ttuttled9dbc652015-09-29 20:00:5916935 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0416936 StaticSocketDataProvider data;
16937 data.set_connect_data(mock_connect);
16938 session_deps_.socket_factory->AddSocketDataProvider(&data);
16939
16940 TestCompletionCallback callback;
16941
tfarina42834112016-09-22 13:38:2016942 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416944
16945 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116946 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0416947
[email protected]79e1fd62013-06-20 06:50:0416948 // We don't care whether this succeeds or fails, but it shouldn't crash.
16949 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616950 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4716951
16952 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1616953 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4716954 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0116955 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5916956
16957 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1616958 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5916959 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0416960}
16961
bncd16676a2016-07-20 16:23:0116962TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0416963 HttpRequestInfo request;
16964 request.method = "GET";
bncce36dca22015-04-21 22:11:2316965 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016966 request.traffic_annotation =
16967 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416968
danakj1fd259a02016-04-16 03:17:0916969 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616970 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416971
16972 MockWrite data_writes[] = {
16973 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
16974 };
16975 MockRead data_reads[] = {
16976 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
16977 };
16978
Ryan Sleevib8d7ea02018-05-07 20:01:0116979 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0416980 session_deps_.socket_factory->AddSocketDataProvider(&data);
16981
16982 TestCompletionCallback callback;
16983
tfarina42834112016-09-22 13:38:2016984 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116985 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416986
16987 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116988 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0416989
[email protected]79e1fd62013-06-20 06:50:0416990 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616991 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0416992 EXPECT_TRUE(request_headers.HasHeader("Host"));
16993}
16994
bncd16676a2016-07-20 16:23:0116995TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0416996 HttpRequestInfo request;
16997 request.method = "GET";
bncce36dca22015-04-21 22:11:2316998 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1016999 request.traffic_annotation =
17000 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417001
danakj1fd259a02016-04-16 03:17:0917002 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617003 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417004
17005 MockWrite data_writes[] = {
17006 MockWrite(ASYNC, ERR_CONNECTION_RESET),
17007 };
17008 MockRead data_reads[] = {
17009 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
17010 };
17011
Ryan Sleevib8d7ea02018-05-07 20:01:0117012 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417013 session_deps_.socket_factory->AddSocketDataProvider(&data);
17014
17015 TestCompletionCallback callback;
17016
tfarina42834112016-09-22 13:38:2017017 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117018 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417019
17020 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117021 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417022
[email protected]79e1fd62013-06-20 06:50:0417023 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617024 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417025 EXPECT_TRUE(request_headers.HasHeader("Host"));
17026}
17027
bncd16676a2016-07-20 16:23:0117028TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417029 HttpRequestInfo request;
17030 request.method = "GET";
bncce36dca22015-04-21 22:11:2317031 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017032 request.traffic_annotation =
17033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417034
danakj1fd259a02016-04-16 03:17:0917035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617036 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417037
17038 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317039 MockWrite(
17040 "GET / HTTP/1.1\r\n"
17041 "Host: www.example.org\r\n"
17042 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417043 };
17044 MockRead data_reads[] = {
17045 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
17046 };
17047
Ryan Sleevib8d7ea02018-05-07 20:01:0117048 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417049 session_deps_.socket_factory->AddSocketDataProvider(&data);
17050
17051 TestCompletionCallback callback;
17052
tfarina42834112016-09-22 13:38:2017053 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417055
17056 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117057 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417058
[email protected]79e1fd62013-06-20 06:50:0417059 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617060 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417061 EXPECT_TRUE(request_headers.HasHeader("Host"));
17062}
17063
bncd16676a2016-07-20 16:23:0117064TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417065 HttpRequestInfo request;
17066 request.method = "GET";
bncce36dca22015-04-21 22:11:2317067 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017068 request.traffic_annotation =
17069 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417070
danakj1fd259a02016-04-16 03:17:0917071 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617072 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417073
17074 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317075 MockWrite(
17076 "GET / HTTP/1.1\r\n"
17077 "Host: www.example.org\r\n"
17078 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417079 };
17080 MockRead data_reads[] = {
17081 MockRead(ASYNC, ERR_CONNECTION_RESET),
17082 };
17083
Ryan Sleevib8d7ea02018-05-07 20:01:0117084 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417085 session_deps_.socket_factory->AddSocketDataProvider(&data);
17086
17087 TestCompletionCallback callback;
17088
tfarina42834112016-09-22 13:38:2017089 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117090 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417091
17092 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117093 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417094
[email protected]79e1fd62013-06-20 06:50:0417095 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617096 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417097 EXPECT_TRUE(request_headers.HasHeader("Host"));
17098}
17099
bncd16676a2016-07-20 16:23:0117100TEST_F(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
[email protected]79e1fd62013-06-20 06:50:0417101 HttpRequestInfo request;
17102 request.method = "GET";
bncce36dca22015-04-21 22:11:2317103 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0417104 request.extra_headers.SetHeader("X-Foo", "bar");
Ramin Halavatib5e433e2018-02-07 07:41:1017105 request.traffic_annotation =
17106 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417107
danakj1fd259a02016-04-16 03:17:0917108 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617109 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417110
17111 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317112 MockWrite(
17113 "GET / HTTP/1.1\r\n"
17114 "Host: www.example.org\r\n"
17115 "Connection: keep-alive\r\n"
17116 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417117 };
17118 MockRead data_reads[] = {
17119 MockRead("HTTP/1.1 200 OK\r\n"
17120 "Content-Length: 5\r\n\r\n"
17121 "hello"),
17122 MockRead(ASYNC, ERR_UNEXPECTED),
17123 };
17124
Ryan Sleevib8d7ea02018-05-07 20:01:0117125 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417126 session_deps_.socket_factory->AddSocketDataProvider(&data);
17127
17128 TestCompletionCallback callback;
17129
tfarina42834112016-09-22 13:38:2017130 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117131 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417132
17133 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117134 EXPECT_THAT(rv, IsOk());
[email protected]79e1fd62013-06-20 06:50:0417135
17136 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617137 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417138 std::string foo;
17139 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
17140 EXPECT_EQ("bar", foo);
17141}
17142
[email protected]043b68c82013-08-22 23:41:5217143// Tests that when a used socket is returned to the SSL socket pool, it's closed
17144// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117145TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5217146 ClientSocketPoolManager::set_max_sockets_per_group(
17147 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17148 ClientSocketPoolManager::set_max_sockets_per_pool(
17149 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17150
17151 // Set up SSL request.
17152
17153 HttpRequestInfo ssl_request;
17154 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2317155 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017156 ssl_request.traffic_annotation =
17157 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217158
17159 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2317160 MockWrite(
17161 "GET / HTTP/1.1\r\n"
17162 "Host: www.example.org\r\n"
17163 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217164 };
17165 MockRead ssl_reads[] = {
17166 MockRead("HTTP/1.1 200 OK\r\n"),
17167 MockRead("Content-Length: 11\r\n\r\n"),
17168 MockRead("hello world"),
17169 MockRead(SYNCHRONOUS, OK),
17170 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117171 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5217172 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17173
17174 SSLSocketDataProvider ssl(ASYNC, OK);
17175 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17176
17177 // Set up HTTP request.
17178
17179 HttpRequestInfo http_request;
17180 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317181 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017182 http_request.traffic_annotation =
17183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217184
17185 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317186 MockWrite(
17187 "GET / HTTP/1.1\r\n"
17188 "Host: www.example.org\r\n"
17189 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217190 };
17191 MockRead http_reads[] = {
17192 MockRead("HTTP/1.1 200 OK\r\n"),
17193 MockRead("Content-Length: 7\r\n\r\n"),
17194 MockRead("falafel"),
17195 MockRead(SYNCHRONOUS, OK),
17196 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117197 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217198 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17199
danakj1fd259a02016-04-16 03:17:0917200 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217201
17202 // Start the SSL request.
17203 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1617204 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017205 ASSERT_EQ(ERR_IO_PENDING,
17206 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
17207 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5217208
17209 // Start the HTTP request. Pool should stall.
17210 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617211 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017212 ASSERT_EQ(ERR_IO_PENDING,
17213 http_trans.Start(&http_request, http_callback.callback(),
17214 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117215 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217216
17217 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0117218 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217219 std::string response_data;
bnc691fda62016-08-12 00:43:1617220 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217221 EXPECT_EQ("hello world", response_data);
17222
17223 // The SSL socket should automatically be closed, so the HTTP request can
17224 // start.
Matt Menke9d5e2c92019-02-05 01:42:2317225 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4117226 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217227
17228 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0117229 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1617230 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217231 EXPECT_EQ("falafel", response_data);
17232
dcheng48459ac22014-08-26 00:46:4117233 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217234}
17235
17236// Tests that when a SSL connection is established but there's no corresponding
17237// request that needs it, the new socket is closed if the transport socket pool
17238// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117239TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5217240 ClientSocketPoolManager::set_max_sockets_per_group(
17241 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17242 ClientSocketPoolManager::set_max_sockets_per_pool(
17243 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17244
17245 // Set up an ssl request.
17246
17247 HttpRequestInfo ssl_request;
17248 ssl_request.method = "GET";
17249 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e2018-02-07 07:41:1017250 ssl_request.traffic_annotation =
17251 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217252
17253 // No data will be sent on the SSL socket.
17254 StaticSocketDataProvider ssl_data;
17255 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17256
17257 SSLSocketDataProvider ssl(ASYNC, OK);
17258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17259
17260 // Set up HTTP request.
17261
17262 HttpRequestInfo http_request;
17263 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317264 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017265 http_request.traffic_annotation =
17266 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217267
17268 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317269 MockWrite(
17270 "GET / HTTP/1.1\r\n"
17271 "Host: www.example.org\r\n"
17272 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217273 };
17274 MockRead http_reads[] = {
17275 MockRead("HTTP/1.1 200 OK\r\n"),
17276 MockRead("Content-Length: 7\r\n\r\n"),
17277 MockRead("falafel"),
17278 MockRead(SYNCHRONOUS, OK),
17279 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117280 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217281 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17282
danakj1fd259a02016-04-16 03:17:0917283 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217284
17285 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
17286 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2917287 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5917288 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2317289 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217290
17291 // Start the HTTP request. Pool should stall.
17292 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617293 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017294 ASSERT_EQ(ERR_IO_PENDING,
17295 http_trans.Start(&http_request, http_callback.callback(),
17296 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117297 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217298
17299 // The SSL connection will automatically be closed once the connection is
17300 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0117301 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217302 std::string response_data;
bnc691fda62016-08-12 00:43:1617303 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217304 EXPECT_EQ("falafel", response_data);
17305
dcheng48459ac22014-08-26 00:46:4117306 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217307}
17308
bncd16676a2016-07-20 16:23:0117309TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917310 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217311 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917312 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217313 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417314
17315 HttpRequestInfo request;
17316 request.method = "POST";
17317 request.url = GURL("http://www.foo.com/");
17318 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017319 request.traffic_annotation =
17320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417321
danakj1fd259a02016-04-16 03:17:0917322 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617323 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417324 // Send headers successfully, but get an error while sending the body.
17325 MockWrite data_writes[] = {
17326 MockWrite("POST / HTTP/1.1\r\n"
17327 "Host: www.foo.com\r\n"
17328 "Connection: keep-alive\r\n"
17329 "Content-Length: 3\r\n\r\n"),
17330 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17331 };
17332
17333 MockRead data_reads[] = {
17334 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17335 MockRead("hello world"),
17336 MockRead(SYNCHRONOUS, OK),
17337 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117338 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417339 session_deps_.socket_factory->AddSocketDataProvider(&data);
17340
17341 TestCompletionCallback callback;
17342
tfarina42834112016-09-22 13:38:2017343 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117344 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417345
17346 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117347 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417348
bnc691fda62016-08-12 00:43:1617349 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217350 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417351
wezca1070932016-05-26 20:30:5217352 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417353 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17354
17355 std::string response_data;
bnc691fda62016-08-12 00:43:1617356 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117357 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417358 EXPECT_EQ("hello world", response_data);
17359}
17360
17361// This test makes sure the retry logic doesn't trigger when reading an error
17362// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0117363TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417364 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0917365 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5417366 MockWrite data_writes[] = {
17367 MockWrite("GET / HTTP/1.1\r\n"
17368 "Host: www.foo.com\r\n"
17369 "Connection: keep-alive\r\n\r\n"),
17370 MockWrite("POST / HTTP/1.1\r\n"
17371 "Host: www.foo.com\r\n"
17372 "Connection: keep-alive\r\n"
17373 "Content-Length: 3\r\n\r\n"),
17374 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17375 };
17376
17377 MockRead data_reads[] = {
17378 MockRead("HTTP/1.1 200 Peachy\r\n"
17379 "Content-Length: 14\r\n\r\n"),
17380 MockRead("first response"),
17381 MockRead("HTTP/1.1 400 Not OK\r\n"
17382 "Content-Length: 15\r\n\r\n"),
17383 MockRead("second response"),
17384 MockRead(SYNCHRONOUS, OK),
17385 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117386 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417387 session_deps_.socket_factory->AddSocketDataProvider(&data);
17388
17389 TestCompletionCallback callback;
17390 HttpRequestInfo request1;
17391 request1.method = "GET";
17392 request1.url = GURL("http://www.foo.com/");
17393 request1.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017394 request1.traffic_annotation =
17395 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417396
bnc87dcefc2017-05-25 12:47:5817397 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1917398 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017399 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117400 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417401
17402 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117403 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417404
17405 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5217406 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5417407
wezca1070932016-05-26 20:30:5217408 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5417409 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
17410
17411 std::string response_data1;
17412 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0117413 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417414 EXPECT_EQ("first response", response_data1);
17415 // Delete the transaction to release the socket back into the socket pool.
17416 trans1.reset();
17417
danakj1fd259a02016-04-16 03:17:0917418 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217419 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917420 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217421 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417422
17423 HttpRequestInfo request2;
17424 request2.method = "POST";
17425 request2.url = GURL("http://www.foo.com/");
17426 request2.upload_data_stream = &upload_data_stream;
17427 request2.load_flags = 0;
Ramin Halavatib5e433e2018-02-07 07:41:1017428 request2.traffic_annotation =
17429 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417430
bnc691fda62016-08-12 00:43:1617431 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017432 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117433 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417434
17435 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117436 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417437
bnc691fda62016-08-12 00:43:1617438 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217439 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5417440
wezca1070932016-05-26 20:30:5217441 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5417442 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
17443
17444 std::string response_data2;
bnc691fda62016-08-12 00:43:1617445 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0117446 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417447 EXPECT_EQ("second response", response_data2);
17448}
17449
bncd16676a2016-07-20 16:23:0117450TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417451 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0917452 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217453 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917454 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217455 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417456
17457 HttpRequestInfo request;
17458 request.method = "POST";
17459 request.url = GURL("http://www.foo.com/");
17460 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017461 request.traffic_annotation =
17462 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417463
danakj1fd259a02016-04-16 03:17:0917464 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617465 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417466 // Send headers successfully, but get an error while sending the body.
17467 MockWrite data_writes[] = {
17468 MockWrite("POST / HTTP/1.1\r\n"
17469 "Host: www.foo.com\r\n"
17470 "Connection: keep-alive\r\n"
17471 "Content-Length: 3\r\n\r\n"
17472 "fo"),
17473 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17474 };
17475
17476 MockRead data_reads[] = {
17477 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17478 MockRead("hello world"),
17479 MockRead(SYNCHRONOUS, OK),
17480 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117481 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417482 session_deps_.socket_factory->AddSocketDataProvider(&data);
17483
17484 TestCompletionCallback callback;
17485
tfarina42834112016-09-22 13:38:2017486 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117487 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417488
17489 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117490 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417491
bnc691fda62016-08-12 00:43:1617492 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217493 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417494
wezca1070932016-05-26 20:30:5217495 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417496 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17497
17498 std::string response_data;
bnc691fda62016-08-12 00:43:1617499 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117500 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417501 EXPECT_EQ("hello world", response_data);
17502}
17503
17504// This tests the more common case than the previous test, where headers and
17505// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0117506TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0717507 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5417508
17509 HttpRequestInfo request;
17510 request.method = "POST";
17511 request.url = GURL("http://www.foo.com/");
17512 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017513 request.traffic_annotation =
17514 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417515
danakj1fd259a02016-04-16 03:17:0917516 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617517 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417518 // Send headers successfully, but get an error while sending the body.
17519 MockWrite data_writes[] = {
17520 MockWrite("POST / HTTP/1.1\r\n"
17521 "Host: www.foo.com\r\n"
17522 "Connection: keep-alive\r\n"
17523 "Transfer-Encoding: chunked\r\n\r\n"),
17524 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17525 };
17526
17527 MockRead data_reads[] = {
17528 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17529 MockRead("hello world"),
17530 MockRead(SYNCHRONOUS, OK),
17531 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117532 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417533 session_deps_.socket_factory->AddSocketDataProvider(&data);
17534
17535 TestCompletionCallback callback;
17536
tfarina42834112016-09-22 13:38:2017537 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117538 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417539 // Make sure the headers are sent before adding a chunk. This ensures that
17540 // they can't be merged with the body in a single send. Not currently
17541 // necessary since a chunked body is never merged with headers, but this makes
17542 // the test more future proof.
17543 base::RunLoop().RunUntilIdle();
17544
mmenkecbc2b712014-10-09 20:29:0717545 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5417546
17547 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117548 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417549
bnc691fda62016-08-12 00:43:1617550 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217551 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417552
wezca1070932016-05-26 20:30:5217553 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417554 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17555
17556 std::string response_data;
bnc691fda62016-08-12 00:43:1617557 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117558 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417559 EXPECT_EQ("hello world", response_data);
17560}
17561
bncd16676a2016-07-20 16:23:0117562TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917563 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217564 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917565 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217566 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417567
17568 HttpRequestInfo request;
17569 request.method = "POST";
17570 request.url = GURL("http://www.foo.com/");
17571 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017572 request.traffic_annotation =
17573 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417574
danakj1fd259a02016-04-16 03:17:0917575 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617576 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417577
17578 MockWrite data_writes[] = {
17579 MockWrite("POST / HTTP/1.1\r\n"
17580 "Host: www.foo.com\r\n"
17581 "Connection: keep-alive\r\n"
17582 "Content-Length: 3\r\n\r\n"),
17583 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17584 };
17585
17586 MockRead data_reads[] = {
17587 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17588 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17589 MockRead("hello world"),
17590 MockRead(SYNCHRONOUS, OK),
17591 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117592 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417593 session_deps_.socket_factory->AddSocketDataProvider(&data);
17594
17595 TestCompletionCallback callback;
17596
tfarina42834112016-09-22 13:38:2017597 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117598 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417599
17600 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117601 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417602
bnc691fda62016-08-12 00:43:1617603 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217604 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417605
wezca1070932016-05-26 20:30:5217606 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417607 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17608
17609 std::string response_data;
bnc691fda62016-08-12 00:43:1617610 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117611 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417612 EXPECT_EQ("hello world", response_data);
17613}
17614
bncd16676a2016-07-20 16:23:0117615TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917616 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217617 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917618 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217619 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417620
17621 HttpRequestInfo request;
17622 request.method = "POST";
17623 request.url = GURL("http://www.foo.com/");
17624 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017625 request.traffic_annotation =
17626 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417627
danakj1fd259a02016-04-16 03:17:0917628 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617629 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417630 // Send headers successfully, but get an error while sending the body.
17631 MockWrite data_writes[] = {
17632 MockWrite("POST / HTTP/1.1\r\n"
17633 "Host: www.foo.com\r\n"
17634 "Connection: keep-alive\r\n"
17635 "Content-Length: 3\r\n\r\n"),
17636 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17637 };
17638
17639 MockRead data_reads[] = {
17640 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
17641 MockRead("hello world"),
17642 MockRead(SYNCHRONOUS, OK),
17643 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117644 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417645 session_deps_.socket_factory->AddSocketDataProvider(&data);
17646
17647 TestCompletionCallback callback;
17648
tfarina42834112016-09-22 13:38:2017649 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117650 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417651
17652 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117653 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417654}
17655
bncd16676a2016-07-20 16:23:0117656TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417657 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917658 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217659 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917660 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217661 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417662
17663 HttpRequestInfo request;
17664 request.method = "POST";
17665 request.url = GURL("http://www.foo.com/");
17666 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017667 request.traffic_annotation =
17668 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417669
danakj1fd259a02016-04-16 03:17:0917670 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617671 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417672 // Send headers successfully, but get an error while sending the body.
17673 MockWrite data_writes[] = {
17674 MockWrite("POST / HTTP/1.1\r\n"
17675 "Host: www.foo.com\r\n"
17676 "Connection: keep-alive\r\n"
17677 "Content-Length: 3\r\n\r\n"),
17678 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17679 };
17680
17681 MockRead data_reads[] = {
17682 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17683 MockRead("HTTP/1.0 302 Redirect\r\n"),
17684 MockRead("Location: http://somewhere-else.com/\r\n"),
17685 MockRead("Content-Length: 0\r\n\r\n"),
17686 MockRead(SYNCHRONOUS, OK),
17687 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117688 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417689 session_deps_.socket_factory->AddSocketDataProvider(&data);
17690
17691 TestCompletionCallback callback;
17692
tfarina42834112016-09-22 13:38:2017693 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117694 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417695
17696 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117697 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417698}
17699
bncd16676a2016-07-20 16:23:0117700TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917701 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217702 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917703 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217704 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417705
17706 HttpRequestInfo request;
17707 request.method = "POST";
17708 request.url = GURL("http://www.foo.com/");
17709 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017710 request.traffic_annotation =
17711 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417712
danakj1fd259a02016-04-16 03:17:0917713 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617714 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417715 // Send headers successfully, but get an error while sending the body.
17716 MockWrite data_writes[] = {
17717 MockWrite("POST / HTTP/1.1\r\n"
17718 "Host: www.foo.com\r\n"
17719 "Connection: keep-alive\r\n"
17720 "Content-Length: 3\r\n\r\n"),
17721 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17722 };
17723
17724 MockRead data_reads[] = {
17725 MockRead("HTTP 0.9 rocks!"),
17726 MockRead(SYNCHRONOUS, OK),
17727 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117728 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417729 session_deps_.socket_factory->AddSocketDataProvider(&data);
17730
17731 TestCompletionCallback callback;
17732
tfarina42834112016-09-22 13:38:2017733 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117734 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417735
17736 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117737 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417738}
17739
bncd16676a2016-07-20 16:23:0117740TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0917741 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217742 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917743 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217744 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417745
17746 HttpRequestInfo request;
17747 request.method = "POST";
17748 request.url = GURL("http://www.foo.com/");
17749 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1017750 request.traffic_annotation =
17751 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417752
danakj1fd259a02016-04-16 03:17:0917753 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617754 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417755 // Send headers successfully, but get an error while sending the body.
17756 MockWrite data_writes[] = {
17757 MockWrite("POST / HTTP/1.1\r\n"
17758 "Host: www.foo.com\r\n"
17759 "Connection: keep-alive\r\n"
17760 "Content-Length: 3\r\n\r\n"),
17761 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17762 };
17763
17764 MockRead data_reads[] = {
17765 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
17766 MockRead(SYNCHRONOUS, OK),
17767 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117768 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417769 session_deps_.socket_factory->AddSocketDataProvider(&data);
17770
17771 TestCompletionCallback callback;
17772
tfarina42834112016-09-22 13:38:2017773 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117774 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417775
17776 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117777 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417778}
17779
Bence Békydca6bd92018-01-30 13:43:0617780#if BUILDFLAG(ENABLE_WEBSOCKETS)
17781
17782namespace {
17783
17784void AddWebSocketHeaders(HttpRequestHeaders* headers) {
17785 headers->SetHeader("Connection", "Upgrade");
17786 headers->SetHeader("Upgrade", "websocket");
17787 headers->SetHeader("Origin", "http://www.example.org");
17788 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0617789}
17790
17791} // namespace
17792
17793TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0117794 for (bool secure : {true, false}) {
17795 MockWrite data_writes[] = {
17796 MockWrite("GET / HTTP/1.1\r\n"
17797 "Host: www.example.org\r\n"
17798 "Connection: Upgrade\r\n"
17799 "Upgrade: websocket\r\n"
17800 "Origin: http://www.example.org\r\n"
17801 "Sec-WebSocket-Version: 13\r\n"
17802 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17803 "Sec-WebSocket-Extensions: permessage-deflate; "
17804 "client_max_window_bits\r\n\r\n")};
17805
17806 MockRead data_reads[] = {
17807 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17808 "Upgrade: websocket\r\n"
17809 "Connection: Upgrade\r\n"
17810 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
17811
Ryan Sleevib8d7ea02018-05-07 20:01:0117812 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0117813 session_deps_.socket_factory->AddSocketDataProvider(&data);
17814 SSLSocketDataProvider ssl(ASYNC, OK);
17815 if (secure)
17816 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0617817
17818 HttpRequestInfo request;
17819 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0117820 request.url =
17821 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
17822 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e2018-02-07 07:41:1017823 request.traffic_annotation =
17824 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0617825
Bence Béky2fcf4fa2018-04-06 20:06:0117826 TestWebSocketHandshakeStreamCreateHelper
17827 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1517828
Bence Béky2fcf4fa2018-04-06 20:06:0117829 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0617830 HttpNetworkTransaction trans(LOW, session.get());
17831 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0117832 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0617833
17834 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0117835 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
17836 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0617837
Bence Béky2fcf4fa2018-04-06 20:06:0117838 const HttpStreamRequest* stream_request = trans.stream_request_.get();
17839 ASSERT_TRUE(stream_request);
17840 EXPECT_EQ(&websocket_handshake_stream_create_helper,
17841 stream_request->websocket_handshake_stream_create_helper());
17842
17843 rv = callback.WaitForResult();
17844 EXPECT_THAT(rv, IsOk());
17845
17846 EXPECT_TRUE(data.AllReadDataConsumed());
17847 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0617848 }
17849}
17850
Adam Rice425cf122015-01-19 06:18:2417851// Verify that proxy headers are not sent to the destination server when
17852// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0117853TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2417854 HttpRequestInfo request;
17855 request.method = "GET";
bncce36dca22015-04-21 22:11:2317856 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017857 request.traffic_annotation =
17858 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417859 AddWebSocketHeaders(&request.extra_headers);
17860
17861 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5917862 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917863 ProxyResolutionService::CreateFixedFromPacResult(
17864 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417865
danakj1fd259a02016-04-16 03:17:0917866 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2417867
17868 // Since a proxy is configured, try to establish a tunnel.
17869 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1717870 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17871 "Host: www.example.org:443\r\n"
17872 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417873
17874 // After calling trans->RestartWithAuth(), this is the request we should
17875 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1717876 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17877 "Host: www.example.org:443\r\n"
17878 "Proxy-Connection: keep-alive\r\n"
17879 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417880
rsleevidb16bb02015-11-12 23:47:1717881 MockWrite("GET / HTTP/1.1\r\n"
17882 "Host: www.example.org\r\n"
17883 "Connection: Upgrade\r\n"
17884 "Upgrade: websocket\r\n"
17885 "Origin: http://www.example.org\r\n"
17886 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1517887 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17888 "Sec-WebSocket-Extensions: permessage-deflate; "
17889 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417890
17891 // The proxy responds to the connect with a 407, using a persistent
17892 // connection.
17893 MockRead data_reads[] = {
17894 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1517895 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
17896 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
17897 "Content-Length: 0\r\n"
17898 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417899
17900 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
17901
Bence Béky8d1c6052018-02-07 12:48:1517902 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17903 "Upgrade: websocket\r\n"
17904 "Connection: Upgrade\r\n"
17905 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417906
Ryan Sleevib8d7ea02018-05-07 20:01:0117907 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2417908 session_deps_.socket_factory->AddSocketDataProvider(&data);
17909 SSLSocketDataProvider ssl(ASYNC, OK);
17910 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17911
Bence Béky8d1c6052018-02-07 12:48:1517912 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
17913
bnc87dcefc2017-05-25 12:47:5817914 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917915 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2417916 trans->SetWebSocketHandshakeStreamCreateHelper(
17917 &websocket_stream_create_helper);
17918
17919 {
17920 TestCompletionCallback callback;
17921
tfarina42834112016-09-22 13:38:2017922 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117923 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2417924
17925 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117926 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2417927 }
17928
17929 const HttpResponseInfo* response = trans->GetResponseInfo();
17930 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5217931 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2417932 EXPECT_EQ(407, response->headers->response_code());
17933
17934 {
17935 TestCompletionCallback callback;
17936
17937 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
17938 callback.callback());
robpercival214763f2016-07-01 23:27:0117939 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2417940
17941 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117942 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2417943 }
17944
17945 response = trans->GetResponseInfo();
17946 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5217947 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2417948
17949 EXPECT_EQ(101, response->headers->response_code());
17950
17951 trans.reset();
17952 session->CloseAllConnections();
17953}
17954
17955// Verify that proxy headers are not sent to the destination server when
17956// establishing a tunnel for an insecure WebSocket connection.
17957// This requires the authentication info to be injected into the auth cache
17958// due to crbug.com/395064
17959// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0117960TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2417961 HttpRequestInfo request;
17962 request.method = "GET";
bncce36dca22015-04-21 22:11:2317963 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1017964 request.traffic_annotation =
17965 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417966 AddWebSocketHeaders(&request.extra_headers);
17967
17968 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5917969 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917970 ProxyResolutionService::CreateFixedFromPacResult(
17971 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417972
danakj1fd259a02016-04-16 03:17:0917973 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2417974
17975 MockWrite data_writes[] = {
17976 // Try to establish a tunnel for the WebSocket connection, with
17977 // credentials. Because WebSockets have a separate set of socket pools,
17978 // they cannot and will not use the same TCP/IP connection as the
17979 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1517980 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
17981 "Host: www.example.org:80\r\n"
17982 "Proxy-Connection: keep-alive\r\n"
17983 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417984
Bence Béky8d1c6052018-02-07 12:48:1517985 MockWrite("GET / HTTP/1.1\r\n"
17986 "Host: www.example.org\r\n"
17987 "Connection: Upgrade\r\n"
17988 "Upgrade: websocket\r\n"
17989 "Origin: http://www.example.org\r\n"
17990 "Sec-WebSocket-Version: 13\r\n"
17991 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17992 "Sec-WebSocket-Extensions: permessage-deflate; "
17993 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417994
17995 MockRead data_reads[] = {
17996 // HTTP CONNECT with credentials.
17997 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
17998
17999 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1518000 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
18001 "Upgrade: websocket\r\n"
18002 "Connection: Upgrade\r\n"
18003 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2418004
Ryan Sleevib8d7ea02018-05-07 20:01:0118005 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2418006 session_deps_.socket_factory->AddSocketDataProvider(&data);
18007
18008 session->http_auth_cache()->Add(
18009 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
18010 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
18011
Bence Béky8d1c6052018-02-07 12:48:1518012 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
18013
bnc87dcefc2017-05-25 12:47:5818014 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1918015 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2418016 trans->SetWebSocketHandshakeStreamCreateHelper(
18017 &websocket_stream_create_helper);
18018
18019 TestCompletionCallback callback;
18020
tfarina42834112016-09-22 13:38:2018021 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118022 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418023
18024 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118025 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418026
18027 const HttpResponseInfo* response = trans->GetResponseInfo();
18028 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218029 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418030
18031 EXPECT_EQ(101, response->headers->response_code());
18032
18033 trans.reset();
18034 session->CloseAllConnections();
18035}
18036
Matt Menke1d6093e32019-03-22 17:33:4318037// WebSockets over QUIC is not supported, including over QUIC proxies.
18038TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18039 for (bool secure : {true, false}) {
18040 SCOPED_TRACE(secure);
18041 session_deps_.proxy_resolution_service =
18042 ProxyResolutionService::CreateFixedFromPacResult(
18043 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18044 session_deps_.enable_quic = true;
18045
18046 HttpRequestInfo request;
18047 request.url =
18048 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18049 AddWebSocketHeaders(&request.extra_headers);
18050 request.traffic_annotation =
18051 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18052
18053 TestWebSocketHandshakeStreamCreateHelper
18054 websocket_handshake_stream_create_helper;
18055
18056 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18057 HttpNetworkTransaction trans(LOW, session.get());
18058 trans.SetWebSocketHandshakeStreamCreateHelper(
18059 &websocket_handshake_stream_create_helper);
18060
18061 TestCompletionCallback callback;
18062 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18064
18065 rv = callback.WaitForResult();
18066 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18067 }
18068}
18069
Bence Békydca6bd92018-01-30 13:43:0618070#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18071
bncd16676a2016-07-20 16:23:0118072TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918073 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218074 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918075 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218076 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218077
18078 HttpRequestInfo request;
18079 request.method = "POST";
18080 request.url = GURL("http://www.foo.com/");
18081 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018082 request.traffic_annotation =
18083 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218084
danakj1fd259a02016-04-16 03:17:0918085 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618086 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218087 MockWrite data_writes[] = {
18088 MockWrite("POST / HTTP/1.1\r\n"
18089 "Host: www.foo.com\r\n"
18090 "Connection: keep-alive\r\n"
18091 "Content-Length: 3\r\n\r\n"),
18092 MockWrite("foo"),
18093 };
18094
18095 MockRead data_reads[] = {
18096 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18097 MockRead(SYNCHRONOUS, OK),
18098 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118099 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218100 session_deps_.socket_factory->AddSocketDataProvider(&data);
18101
18102 TestCompletionCallback callback;
18103
18104 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018105 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118106 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218107
18108 std::string response_data;
bnc691fda62016-08-12 00:43:1618109 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218110
Ryan Sleevib8d7ea02018-05-07 20:01:0118111 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18112 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218113}
18114
bncd16676a2016-07-20 16:23:0118115TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0918116 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218117 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918118 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218119 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218120
18121 HttpRequestInfo request;
18122 request.method = "POST";
18123 request.url = GURL("http://www.foo.com/");
18124 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018125 request.traffic_annotation =
18126 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218127
danakj1fd259a02016-04-16 03:17:0918128 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618129 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218130 MockWrite data_writes[] = {
18131 MockWrite("POST / HTTP/1.1\r\n"
18132 "Host: www.foo.com\r\n"
18133 "Connection: keep-alive\r\n"
18134 "Content-Length: 3\r\n\r\n"),
18135 MockWrite("foo"),
18136 };
18137
18138 MockRead data_reads[] = {
18139 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
18140 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18141 MockRead(SYNCHRONOUS, OK),
18142 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118143 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218144 session_deps_.socket_factory->AddSocketDataProvider(&data);
18145
18146 TestCompletionCallback callback;
18147
18148 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018149 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118150 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218151
18152 std::string response_data;
bnc691fda62016-08-12 00:43:1618153 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218154
Ryan Sleevib8d7ea02018-05-07 20:01:0118155 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18156 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218157}
18158
bncd16676a2016-07-20 16:23:0118159TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2218160 ChunkedUploadDataStream upload_data_stream(0);
18161
18162 HttpRequestInfo request;
18163 request.method = "POST";
18164 request.url = GURL("http://www.foo.com/");
18165 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e2018-02-07 07:41:1018166 request.traffic_annotation =
18167 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218168
danakj1fd259a02016-04-16 03:17:0918169 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618170 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218171 // Send headers successfully, but get an error while sending the body.
18172 MockWrite data_writes[] = {
18173 MockWrite("POST / HTTP/1.1\r\n"
18174 "Host: www.foo.com\r\n"
18175 "Connection: keep-alive\r\n"
18176 "Transfer-Encoding: chunked\r\n\r\n"),
18177 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
18178 };
18179
18180 MockRead data_reads[] = {
18181 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18182 MockRead(SYNCHRONOUS, OK),
18183 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118184 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218185 session_deps_.socket_factory->AddSocketDataProvider(&data);
18186
18187 TestCompletionCallback callback;
18188
18189 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018190 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2218191
18192 base::RunLoop().RunUntilIdle();
18193 upload_data_stream.AppendData("f", 1, false);
18194
18195 base::RunLoop().RunUntilIdle();
18196 upload_data_stream.AppendData("oo", 2, true);
18197
robpercival214763f2016-07-01 23:27:0118198 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218199
18200 std::string response_data;
bnc691fda62016-08-12 00:43:1618201 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218202
Ryan Sleevib8d7ea02018-05-07 20:01:0118203 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18204 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218205}
18206
eustasc7d27da2017-04-06 10:33:2018207void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
18208 const std::string& accept_encoding,
18209 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0318210 const std::string& location,
eustasc7d27da2017-04-06 10:33:2018211 bool should_match) {
18212 HttpRequestInfo request;
18213 request.method = "GET";
18214 request.url = GURL("http://www.foo.com/");
18215 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
18216 accept_encoding);
Ramin Halavatib5e433e2018-02-07 07:41:1018217 request.traffic_annotation =
18218 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2018219
18220 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
18221 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18222 // Send headers successfully, but get an error while sending the body.
18223 MockWrite data_writes[] = {
18224 MockWrite("GET / HTTP/1.1\r\n"
18225 "Host: www.foo.com\r\n"
18226 "Connection: keep-alive\r\n"
18227 "Accept-Encoding: "),
18228 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
18229 };
18230
sky50576f32017-05-01 19:28:0318231 std::string response_code = "200 OK";
18232 std::string extra;
18233 if (!location.empty()) {
18234 response_code = "301 Redirect\r\nLocation: ";
18235 response_code.append(location);
18236 }
18237
eustasc7d27da2017-04-06 10:33:2018238 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0318239 MockRead("HTTP/1.0 "),
18240 MockRead(response_code.data()),
18241 MockRead("\r\nContent-Encoding: "),
18242 MockRead(content_encoding.data()),
18243 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2018244 MockRead(SYNCHRONOUS, OK),
18245 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118246 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2018247 session_deps->socket_factory->AddSocketDataProvider(&data);
18248
18249 TestCompletionCallback callback;
18250
18251 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18252 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18253
18254 rv = callback.WaitForResult();
18255 if (should_match) {
18256 EXPECT_THAT(rv, IsOk());
18257 } else {
18258 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
18259 }
18260}
18261
18262TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0318263 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2018264}
18265
18266TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0318267 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
18268 true);
eustasc7d27da2017-04-06 10:33:2018269}
18270
18271TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
18272 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0318273 "", false);
18274}
18275
18276TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
18277 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
18278 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2018279}
18280
xunjieli96f2a402017-06-05 17:24:2718281TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
18282 ProxyConfig proxy_config;
18283 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18284 proxy_config.set_pac_mandatory(true);
18285 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918286 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918287 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18288 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0418289 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2718290
18291 HttpRequestInfo request;
18292 request.method = "GET";
18293 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018294 request.traffic_annotation =
18295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718296
18297 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18298 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18299
18300 TestCompletionCallback callback;
18301
18302 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18303 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18304 EXPECT_THAT(callback.WaitForResult(),
18305 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18306}
18307
18308TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
18309 ProxyConfig proxy_config;
18310 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18311 proxy_config.set_pac_mandatory(true);
18312 MockAsyncProxyResolverFactory* proxy_resolver_factory =
18313 new MockAsyncProxyResolverFactory(false);
18314 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918315 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918316 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18317 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5918318 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2718319 HttpRequestInfo request;
18320 request.method = "GET";
18321 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018322 request.traffic_annotation =
18323 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718324
18325 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18326 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18327
18328 TestCompletionCallback callback;
18329 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18331
18332 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
18333 ERR_FAILED, &resolver);
18334 EXPECT_THAT(callback.WaitForResult(),
18335 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18336}
18337
18338TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5918339 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918340 ProxyResolutionService::CreateFixedFromPacResult(
18341 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718342 session_deps_.enable_quic = false;
18343 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18344
18345 HttpRequestInfo request;
18346 request.method = "GET";
18347 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e2018-02-07 07:41:1018348 request.traffic_annotation =
18349 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718350
18351 TestCompletionCallback callback;
18352 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18353 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18354 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18355
18356 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
18357}
18358
Douglas Creager3cb042052018-11-06 23:08:5218359//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1418360// Reporting tests
18361
18362#if BUILDFLAG(ENABLE_REPORTING)
18363class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
18364 protected:
18365 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618366 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1418367 auto test_reporting_context = std::make_unique<TestReportingContext>(
18368 &clock_, &tick_clock_, ReportingPolicy());
18369 test_reporting_context_ = test_reporting_context.get();
18370 session_deps_.reporting_service =
18371 ReportingService::CreateForTesting(std::move(test_reporting_context));
18372 }
18373
18374 TestReportingContext* reporting_context() const {
18375 return test_reporting_context_;
18376 }
18377
18378 void clear_reporting_service() {
18379 session_deps_.reporting_service.reset();
18380 test_reporting_context_ = nullptr;
18381 }
18382
18383 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4218384 void RequestPolicy(CertStatus cert_status = 0) {
18385 HttpRequestInfo request;
18386 request.method = "GET";
18387 request.url = GURL(url_);
18388 request.traffic_annotation =
18389 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18390
Lily Chend3930e72019-03-01 19:31:1118391 MockWrite data_writes[] = {
18392 MockWrite("GET / HTTP/1.1\r\n"
18393 "Host: www.example.org\r\n"
18394 "Connection: keep-alive\r\n\r\n"),
18395 };
Douglas Creager134b52e2018-11-09 18:00:1418396 MockRead data_reads[] = {
18397 MockRead("HTTP/1.0 200 OK\r\n"),
18398 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
18399 "\"endpoints\": [{\"url\": "
18400 "\"https://www.example.org/upload/\"}]}\r\n"),
18401 MockRead("\r\n"),
18402 MockRead("hello world"),
18403 MockRead(SYNCHRONOUS, OK),
18404 };
Douglas Creager134b52e2018-11-09 18:00:1418405
Lily Chenfec60d92019-01-24 01:16:4218406 StaticSocketDataProvider reads(data_reads, data_writes);
18407 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1418408
18409 SSLSocketDataProvider ssl(ASYNC, OK);
18410 if (request.url.SchemeIsCryptographic()) {
18411 ssl.ssl_info.cert =
18412 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18413 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218414 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1418415 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18416 }
18417
Douglas Creager134b52e2018-11-09 18:00:1418418 TestCompletionCallback callback;
18419 auto session = CreateSession(&session_deps_);
18420 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18421 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4218422 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1418423 }
18424
18425 protected:
18426 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1418427
18428 private:
18429 TestReportingContext* test_reporting_context_;
18430};
18431
18432TEST_F(HttpNetworkTransactionReportingTest,
18433 DontProcessReportToHeaderNoService) {
18434 base::HistogramTester histograms;
18435 clear_reporting_service();
18436 RequestPolicy();
18437 histograms.ExpectBucketCount(
18438 ReportingHeaderParser::kHeaderOutcomeHistogram,
18439 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
18440}
18441
18442TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
18443 base::HistogramTester histograms;
18444 url_ = "http://www.example.org/";
18445 RequestPolicy();
18446 histograms.ExpectBucketCount(
18447 ReportingHeaderParser::kHeaderOutcomeHistogram,
18448 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18449}
18450
18451TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
18452 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5418453 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
18454 const ReportingClient endpoint =
18455 reporting_context()->cache()->GetEndpointForTesting(
18456 url::Origin::Create(GURL("https://www.example.org/")), "nel",
18457 GURL("https://www.example.org/upload/"));
18458 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1418459}
18460
18461TEST_F(HttpNetworkTransactionReportingTest,
18462 DontProcessReportToHeaderInvalidHttps) {
18463 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218464 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18465 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1418466 histograms.ExpectBucketCount(
18467 ReportingHeaderParser::kHeaderOutcomeHistogram,
18468 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
18469}
18470#endif // BUILDFLAG(ENABLE_REPORTING)
18471
18472//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5218473// Network Error Logging tests
18474
18475#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4218476namespace {
18477
18478const char kUserAgent[] = "Mozilla/1.0";
18479const char kReferrer[] = "https://www.referrer.org/";
18480
18481} // namespace
18482
Douglas Creager3cb042052018-11-06 23:08:5218483class HttpNetworkTransactionNetworkErrorLoggingTest
18484 : public HttpNetworkTransactionTest {
18485 protected:
18486 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618487 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5218488 auto network_error_logging_service =
18489 std::make_unique<TestNetworkErrorLoggingService>();
18490 test_network_error_logging_service_ = network_error_logging_service.get();
18491 session_deps_.network_error_logging_service =
18492 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4218493
18494 extra_headers_.SetHeader("User-Agent", kUserAgent);
18495 extra_headers_.SetHeader("Referer", kReferrer);
18496
18497 request_.method = "GET";
18498 request_.url = GURL(url_);
18499 request_.extra_headers = extra_headers_;
18500 request_.reporting_upload_depth = reporting_upload_depth_;
18501 request_.traffic_annotation =
18502 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5218503 }
18504
18505 TestNetworkErrorLoggingService* network_error_logging_service() const {
18506 return test_network_error_logging_service_;
18507 }
18508
18509 void clear_network_error_logging_service() {
18510 session_deps_.network_error_logging_service.reset();
18511 test_network_error_logging_service_ = nullptr;
18512 }
18513
18514 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4218515 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3618516 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318517 MockWrite data_writes[] = {
18518 MockWrite("GET / HTTP/1.1\r\n"
18519 "Host: www.example.org\r\n"
18520 "Connection: keep-alive\r\n"),
18521 MockWrite(ASYNC, extra_header_string.data(),
18522 extra_header_string.size()),
18523 };
Lily Chend3930e72019-03-01 19:31:1118524 MockRead data_reads[] = {
18525 MockRead("HTTP/1.0 200 OK\r\n"),
18526 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18527 MockRead("\r\n"),
18528 MockRead("hello world"),
18529 MockRead(SYNCHRONOUS, OK),
18530 };
Douglas Creager3cb042052018-11-06 23:08:5218531
Lily Chenfec60d92019-01-24 01:16:4218532 StaticSocketDataProvider reads(data_reads, data_writes);
18533 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5218534
18535 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4218536 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5218537 ssl.ssl_info.cert =
18538 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18539 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218540 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5218541 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18542 }
18543
Douglas Creager3cb042052018-11-06 23:08:5218544 TestCompletionCallback callback;
18545 auto session = CreateSession(&session_deps_);
18546 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4218547 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
18548 EXPECT_THAT(callback.GetResult(rv), IsOk());
18549
18550 std::string response_data;
18551 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18552 EXPECT_EQ("hello world", response_data);
18553 }
18554
18555 void CheckReport(size_t index,
18556 int status_code,
18557 int error_type,
18558 IPAddress server_ip = IPAddress::IPv4Localhost()) {
18559 ASSERT_LT(index, network_error_logging_service()->errors().size());
18560
18561 const NetworkErrorLoggingService::RequestDetails& error =
18562 network_error_logging_service()->errors()[index];
18563 EXPECT_EQ(url_, error.uri);
18564 EXPECT_EQ(kReferrer, error.referrer);
18565 EXPECT_EQ(kUserAgent, error.user_agent);
18566 EXPECT_EQ(server_ip, error.server_ip);
18567 EXPECT_EQ("http/1.1", error.protocol);
18568 EXPECT_EQ("GET", error.method);
18569 EXPECT_EQ(status_code, error.status_code);
18570 EXPECT_EQ(error_type, error.type);
18571 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5218572 }
18573
18574 protected:
18575 std::string url_ = "https://www.example.org/";
18576 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4218577 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3618578 HttpRequestHeaders extra_headers_;
18579 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5218580
18581 private:
18582 TestNetworkErrorLoggingService* test_network_error_logging_service_;
18583};
18584
18585TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18586 DontProcessNelHeaderNoService) {
18587 base::HistogramTester histograms;
18588 clear_network_error_logging_service();
18589 RequestPolicy();
18590 histograms.ExpectBucketCount(
18591 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18592 NetworkErrorLoggingService::HeaderOutcome::
18593 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
18594 1);
18595}
18596
18597TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18598 DontProcessNelHeaderHttp) {
18599 base::HistogramTester histograms;
18600 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4218601 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5218602 RequestPolicy();
18603 histograms.ExpectBucketCount(
18604 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18605 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18606}
18607
Lily Chen90ae93cc2019-02-14 01:15:3918608// Don't set NEL policies received on a proxied connection.
18609TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18610 DontProcessNelHeaderProxy) {
18611 session_deps_.proxy_resolution_service =
18612 ProxyResolutionService::CreateFixedFromPacResult(
18613 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
18614 BoundTestNetLog log;
18615 session_deps_.net_log = log.bound().net_log();
18616 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18617
18618 HttpRequestInfo request;
18619 request.method = "GET";
18620 request.url = GURL("https://www.example.org/");
18621 request.traffic_annotation =
18622 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18623
18624 // Since we have proxy, should try to establish tunnel.
18625 MockWrite data_writes1[] = {
18626 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18627 "Host: www.example.org:443\r\n"
18628 "Proxy-Connection: keep-alive\r\n\r\n"),
18629
18630 MockWrite("GET / HTTP/1.1\r\n"
18631 "Host: www.example.org\r\n"
18632 "Connection: keep-alive\r\n\r\n"),
18633 };
18634
18635 MockRead data_reads1[] = {
18636 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18637
18638 MockRead("HTTP/1.1 200 OK\r\n"),
18639 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18640 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18641 MockRead("Content-Length: 100\r\n\r\n"),
18642 MockRead(SYNCHRONOUS, OK),
18643 };
18644
18645 StaticSocketDataProvider data1(data_reads1, data_writes1);
18646 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18647 SSLSocketDataProvider ssl(ASYNC, OK);
18648 ssl.ssl_info.cert =
18649 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18650 ASSERT_TRUE(ssl.ssl_info.cert);
18651 ssl.ssl_info.cert_status = 0;
18652 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18653
18654 TestCompletionCallback callback1;
18655 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18656
18657 int rv = trans.Start(&request, callback1.callback(), log.bound());
18658 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18659
18660 rv = callback1.WaitForResult();
18661 EXPECT_THAT(rv, IsOk());
18662
18663 const HttpResponseInfo* response = trans.GetResponseInfo();
18664 ASSERT_TRUE(response);
18665 EXPECT_EQ(200, response->headers->response_code());
18666 EXPECT_TRUE(response->was_fetched_via_proxy);
18667
18668 // No NEL header was set.
18669 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
18670}
18671
Douglas Creager3cb042052018-11-06 23:08:5218672TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
18673 RequestPolicy();
18674 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
18675 const auto& header = network_error_logging_service()->headers()[0];
18676 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
18677 header.origin);
18678 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
18679 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
18680}
18681
18682TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18683 DontProcessNelHeaderInvalidHttps) {
18684 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218685 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18686 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5218687 histograms.ExpectBucketCount(
18688 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18689 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
18690 1);
18691}
Douglas Creageref5eecdc2018-11-09 20:50:3618692
Lily Chenfec60d92019-01-24 01:16:4218693TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3618694 RequestPolicy();
18695 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4218696 CheckReport(0 /* index */, 200 /* status_code */, OK);
18697}
18698
18699TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18700 CreateReportErrorAfterStart) {
18701 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18702 auto trans =
18703 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18704
18705 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
18706 StaticSocketDataProvider data;
18707 data.set_connect_data(mock_connect);
18708 session_deps_.socket_factory->AddSocketDataProvider(&data);
18709
18710 TestCompletionCallback callback;
18711
18712 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18713 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18714
18715 trans.reset();
18716
18717 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18718 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18719 IPAddress() /* server_ip */);
18720}
18721
18722// Same as above except the error is ASYNC
18723TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18724 CreateReportErrorAfterStartAsync) {
18725 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18726 auto trans =
18727 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18728
18729 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
18730 StaticSocketDataProvider data;
18731 data.set_connect_data(mock_connect);
18732 session_deps_.socket_factory->AddSocketDataProvider(&data);
18733
18734 TestCompletionCallback callback;
18735
18736 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18737 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18738
18739 trans.reset();
18740
18741 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18742 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18743 IPAddress() /* server_ip */);
18744}
18745
18746TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18747 CreateReportReadBodyError) {
18748 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318749 MockWrite data_writes[] = {
18750 MockWrite("GET / HTTP/1.1\r\n"
18751 "Host: www.example.org\r\n"
18752 "Connection: keep-alive\r\n"),
18753 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18754 };
Lily Chend3930e72019-03-01 19:31:1118755 MockRead data_reads[] = {
18756 MockRead("HTTP/1.0 200 OK\r\n"),
18757 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18758 MockRead("hello world"),
18759 MockRead(SYNCHRONOUS, OK),
18760 };
Lily Chenfec60d92019-01-24 01:16:4218761
18762 StaticSocketDataProvider reads(data_reads, data_writes);
18763 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18764
18765 SSLSocketDataProvider ssl(ASYNC, OK);
18766 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18767
18768 // Log start time
18769 base::TimeTicks start_time = base::TimeTicks::Now();
18770
18771 TestCompletionCallback callback;
18772 auto session = CreateSession(&session_deps_);
18773 auto trans =
18774 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18775 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18776 EXPECT_THAT(callback.GetResult(rv), IsOk());
18777
18778 const HttpResponseInfo* response = trans->GetResponseInfo();
18779 ASSERT_TRUE(response);
18780
18781 EXPECT_TRUE(response->headers);
18782 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18783
18784 std::string response_data;
18785 rv = ReadTransaction(trans.get(), &response_data);
18786 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18787
18788 trans.reset();
18789
18790 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18791
18792 CheckReport(0 /* index */, 200 /* status_code */,
18793 ERR_CONTENT_LENGTH_MISMATCH);
18794 const NetworkErrorLoggingService::RequestDetails& error =
18795 network_error_logging_service()->errors()[0];
18796 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18797}
18798
18799// Same as above except the final read is ASYNC.
18800TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18801 CreateReportReadBodyErrorAsync) {
18802 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318803 MockWrite data_writes[] = {
18804 MockWrite("GET / HTTP/1.1\r\n"
18805 "Host: www.example.org\r\n"
18806 "Connection: keep-alive\r\n"),
18807 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18808 };
Lily Chend3930e72019-03-01 19:31:1118809 MockRead data_reads[] = {
18810 MockRead("HTTP/1.0 200 OK\r\n"),
18811 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18812 MockRead("hello world"),
18813 MockRead(ASYNC, OK),
18814 };
Lily Chenfec60d92019-01-24 01:16:4218815
18816 StaticSocketDataProvider reads(data_reads, data_writes);
18817 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18818
18819 SSLSocketDataProvider ssl(ASYNC, OK);
18820 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18821
18822 // Log start time
18823 base::TimeTicks start_time = base::TimeTicks::Now();
18824
18825 TestCompletionCallback callback;
18826 auto session = CreateSession(&session_deps_);
18827 auto trans =
18828 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18829 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18830 EXPECT_THAT(callback.GetResult(rv), IsOk());
18831
18832 const HttpResponseInfo* response = trans->GetResponseInfo();
18833 ASSERT_TRUE(response);
18834
18835 EXPECT_TRUE(response->headers);
18836 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18837
18838 std::string response_data;
18839 rv = ReadTransaction(trans.get(), &response_data);
18840 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18841
18842 trans.reset();
18843
18844 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18845
18846 CheckReport(0 /* index */, 200 /* status_code */,
18847 ERR_CONTENT_LENGTH_MISMATCH);
18848 const NetworkErrorLoggingService::RequestDetails& error =
18849 network_error_logging_service()->errors()[0];
18850 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18851}
18852
18853TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18854 CreateReportRestartWithAuth) {
18855 std::string extra_header_string = extra_headers_.ToString();
18856 static const base::TimeDelta kSleepDuration =
18857 base::TimeDelta::FromMilliseconds(10);
18858
18859 MockWrite data_writes1[] = {
18860 MockWrite("GET / HTTP/1.1\r\n"
18861 "Host: www.example.org\r\n"
18862 "Connection: keep-alive\r\n"),
18863 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18864 };
18865
18866 MockRead data_reads1[] = {
18867 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
18868 // Give a couple authenticate options (only the middle one is actually
18869 // supported).
18870 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
18871 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
18872 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
18873 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18874 // Large content-length -- won't matter, as connection will be reset.
18875 MockRead("Content-Length: 10000\r\n\r\n"),
18876 MockRead(SYNCHRONOUS, ERR_FAILED),
18877 };
18878
18879 // After calling trans->RestartWithAuth(), this is the request we should
18880 // be issuing -- the final header line contains the credentials.
18881 MockWrite data_writes2[] = {
18882 MockWrite("GET / HTTP/1.1\r\n"
18883 "Host: www.example.org\r\n"
18884 "Connection: keep-alive\r\n"
18885 "Authorization: Basic Zm9vOmJhcg==\r\n"),
18886 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18887 };
18888
18889 // Lastly, the server responds with the actual content.
18890 MockRead data_reads2[] = {
18891 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
18892 MockRead("hello world"),
18893 MockRead(SYNCHRONOUS, OK),
18894 };
18895
18896 StaticSocketDataProvider data1(data_reads1, data_writes1);
18897 StaticSocketDataProvider data2(data_reads2, data_writes2);
18898 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18899 session_deps_.socket_factory->AddSocketDataProvider(&data2);
18900
18901 SSLSocketDataProvider ssl1(ASYNC, OK);
18902 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18903 SSLSocketDataProvider ssl2(ASYNC, OK);
18904 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18905
18906 base::TimeTicks start_time = base::TimeTicks::Now();
18907 base::TimeTicks restart_time;
18908
18909 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18910 auto trans =
18911 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18912
18913 TestCompletionCallback callback1;
18914
18915 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
18916 EXPECT_THAT(callback1.GetResult(rv), IsOk());
18917
18918 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18919
18920 TestCompletionCallback callback2;
18921
18922 // Wait 10 ms then restart with auth
18923 FastForwardBy(kSleepDuration);
18924 restart_time = base::TimeTicks::Now();
18925 rv =
18926 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
18927 EXPECT_THAT(callback2.GetResult(rv), IsOk());
18928
18929 std::string response_data;
18930 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
18931 EXPECT_EQ("hello world", response_data);
18932
18933 trans.reset();
18934
18935 // One 401 report for the auth challenge, then a 200 report for the successful
18936 // retry. Note that we don't report the error draining the body, as the first
18937 // request already generated a report for the auth challenge.
18938 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
18939
18940 // Check error report contents
18941 CheckReport(0 /* index */, 401 /* status_code */, OK);
18942 CheckReport(1 /* index */, 200 /* status_code */, OK);
18943
18944 const NetworkErrorLoggingService::RequestDetails& error1 =
18945 network_error_logging_service()->errors()[0];
18946 const NetworkErrorLoggingService::RequestDetails& error2 =
18947 network_error_logging_service()->errors()[1];
18948
18949 // Sanity-check elapsed time values
18950 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
18951 // Check that the start time is refreshed when restarting with auth.
18952 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
18953}
18954
18955// Same as above, except draining the body before restarting fails
18956// asynchronously.
18957TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18958 CreateReportRestartWithAuthAsync) {
18959 std::string extra_header_string = extra_headers_.ToString();
18960 static const base::TimeDelta kSleepDuration =
18961 base::TimeDelta::FromMilliseconds(10);
18962
18963 MockWrite data_writes1[] = {
18964 MockWrite("GET / HTTP/1.1\r\n"
18965 "Host: www.example.org\r\n"
18966 "Connection: keep-alive\r\n"),
18967 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18968 };
18969
18970 MockRead data_reads1[] = {
18971 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
18972 // Give a couple authenticate options (only the middle one is actually
18973 // supported).
18974 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
18975 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
18976 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
18977 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18978 // Large content-length -- won't matter, as connection will be reset.
18979 MockRead("Content-Length: 10000\r\n\r\n"),
18980 MockRead(ASYNC, ERR_FAILED),
18981 };
18982
18983 // After calling trans->RestartWithAuth(), this is the request we should
18984 // be issuing -- the final header line contains the credentials.
18985 MockWrite data_writes2[] = {
18986 MockWrite("GET / HTTP/1.1\r\n"
18987 "Host: www.example.org\r\n"
18988 "Connection: keep-alive\r\n"
18989 "Authorization: Basic Zm9vOmJhcg==\r\n"),
18990 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18991 };
18992
18993 // Lastly, the server responds with the actual content.
18994 MockRead data_reads2[] = {
18995 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
18996 MockRead("hello world"),
18997 MockRead(SYNCHRONOUS, OK),
18998 };
18999
19000 StaticSocketDataProvider data1(data_reads1, data_writes1);
19001 StaticSocketDataProvider data2(data_reads2, data_writes2);
19002 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19003 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19004
19005 SSLSocketDataProvider ssl1(ASYNC, OK);
19006 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19007 SSLSocketDataProvider ssl2(ASYNC, OK);
19008 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19009
19010 base::TimeTicks start_time = base::TimeTicks::Now();
19011 base::TimeTicks restart_time;
19012
19013 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19014 auto trans =
19015 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19016
19017 TestCompletionCallback callback1;
19018
19019 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19020 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19021
19022 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19023
19024 TestCompletionCallback callback2;
19025
19026 // Wait 10 ms then restart with auth
19027 FastForwardBy(kSleepDuration);
19028 restart_time = base::TimeTicks::Now();
19029 rv =
19030 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19031 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19032
19033 std::string response_data;
19034 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19035 EXPECT_EQ("hello world", response_data);
19036
19037 trans.reset();
19038
19039 // One 401 report for the auth challenge, then a 200 report for the successful
19040 // retry. Note that we don't report the error draining the body, as the first
19041 // request already generated a report for the auth challenge.
19042 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19043
19044 // Check error report contents
19045 CheckReport(0 /* index */, 401 /* status_code */, OK);
19046 CheckReport(1 /* index */, 200 /* status_code */, OK);
19047
19048 const NetworkErrorLoggingService::RequestDetails& error1 =
19049 network_error_logging_service()->errors()[0];
19050 const NetworkErrorLoggingService::RequestDetails& error2 =
19051 network_error_logging_service()->errors()[1];
19052
19053 // Sanity-check elapsed time values
19054 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19055 // Check that the start time is refreshed when restarting with auth.
19056 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19057}
19058
19059TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19060 CreateReportRetryKeepAliveConnectionReset) {
19061 std::string extra_header_string = extra_headers_.ToString();
19062 MockWrite data_writes1[] = {
19063 MockWrite("GET / HTTP/1.1\r\n"
19064 "Host: www.example.org\r\n"
19065 "Connection: keep-alive\r\n"),
19066 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19067 MockWrite("GET / HTTP/1.1\r\n"
19068 "Host: www.example.org\r\n"
19069 "Connection: keep-alive\r\n"),
19070 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19071 };
19072
19073 MockRead data_reads1[] = {
19074 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19075 MockRead("hello"),
19076 // Connection is reset
19077 MockRead(ASYNC, ERR_CONNECTION_RESET),
19078 };
19079
19080 // Successful retry
19081 MockRead data_reads2[] = {
19082 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19083 MockRead("world"),
19084 MockRead(ASYNC, OK),
19085 };
19086
19087 StaticSocketDataProvider data1(data_reads1, data_writes1);
19088 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19089 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19090 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19091
19092 SSLSocketDataProvider ssl1(ASYNC, OK);
19093 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19094 SSLSocketDataProvider ssl2(ASYNC, OK);
19095 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19096
19097 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19098 auto trans1 =
19099 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19100
19101 TestCompletionCallback callback1;
19102
19103 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19104 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19105
19106 std::string response_data;
19107 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19108 EXPECT_EQ("hello", response_data);
19109
19110 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19111
19112 auto trans2 =
19113 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19114
19115 TestCompletionCallback callback2;
19116
19117 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19118 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19119
19120 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19121 EXPECT_EQ("world", response_data);
19122
19123 trans1.reset();
19124 trans2.reset();
19125
19126 // One OK report from first request, then a ERR_CONNECTION_RESET report from
19127 // the second request, then an OK report from the successful retry.
19128 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19129
19130 // Check error report contents
19131 CheckReport(0 /* index */, 200 /* status_code */, OK);
19132 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
19133 CheckReport(2 /* index */, 200 /* status_code */, OK);
19134}
19135
19136TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19137 CreateReportRetryKeepAlive408) {
19138 std::string extra_header_string = extra_headers_.ToString();
19139 MockWrite data_writes1[] = {
19140 MockWrite("GET / HTTP/1.1\r\n"
19141 "Host: www.example.org\r\n"
19142 "Connection: keep-alive\r\n"),
19143 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19144 MockWrite("GET / HTTP/1.1\r\n"
19145 "Host: www.example.org\r\n"
19146 "Connection: keep-alive\r\n"),
19147 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19148 };
19149
19150 MockRead data_reads1[] = {
19151 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19152 MockRead("hello"),
19153 // 408 Request Timeout
19154 MockRead(SYNCHRONOUS,
19155 "HTTP/1.1 408 Request Timeout\r\n"
19156 "Connection: Keep-Alive\r\n"
19157 "Content-Length: 6\r\n\r\n"
19158 "Pickle"),
19159 };
19160
19161 // Successful retry
19162 MockRead data_reads2[] = {
19163 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19164 MockRead("world"),
19165 MockRead(ASYNC, OK),
19166 };
19167
19168 StaticSocketDataProvider data1(data_reads1, data_writes1);
19169 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19170 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19171 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19172
19173 SSLSocketDataProvider ssl1(ASYNC, OK);
19174 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19175 SSLSocketDataProvider ssl2(ASYNC, OK);
19176 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19177
19178 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19179 auto trans1 =
19180 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19181
19182 TestCompletionCallback callback1;
19183
19184 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19185 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19186
19187 std::string response_data;
19188 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19189 EXPECT_EQ("hello", response_data);
19190
19191 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19192
19193 auto trans2 =
19194 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19195
19196 TestCompletionCallback callback2;
19197
19198 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19199 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19200
19201 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19202 EXPECT_EQ("world", response_data);
19203
19204 trans1.reset();
19205 trans2.reset();
19206
19207 // One 200 report from first request, then a 408 report from
19208 // the second request, then a 200 report from the successful retry.
19209 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19210
19211 // Check error report contents
19212 CheckReport(0 /* index */, 200 /* status_code */, OK);
19213 CheckReport(1 /* index */, 408 /* status_code */, OK);
19214 CheckReport(2 /* index */, 200 /* status_code */, OK);
19215}
19216
19217TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19218 CreateReportRetry421WithoutConnectionPooling) {
19219 // Two hosts resolve to the same IP address.
19220 const std::string ip_addr = "1.2.3.4";
19221 IPAddress ip;
19222 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
19223 IPEndPoint peer_addr = IPEndPoint(ip, 443);
19224
19225 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19226 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
19227 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
19228
19229 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19230
19231 // Two requests on the first connection.
19232 spdy::SpdySerializedFrame req1(
19233 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19234 spdy_util_.UpdateWithStreamDestruction(1);
19235 spdy::SpdySerializedFrame req2(
19236 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
19237 spdy::SpdySerializedFrame rst(
19238 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
19239 MockWrite writes1[] = {
19240 CreateMockWrite(req1, 0),
19241 CreateMockWrite(req2, 3),
19242 CreateMockWrite(rst, 6),
19243 };
19244
19245 // The first one succeeds, the second gets error 421 Misdirected Request.
19246 spdy::SpdySerializedFrame resp1(
19247 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19248 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
19249 spdy::SpdyHeaderBlock response_headers;
19250 response_headers[spdy::kHttp2StatusHeader] = "421";
19251 spdy::SpdySerializedFrame resp2(
19252 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
19253 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
19254 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
19255
19256 MockConnect connect1(ASYNC, OK, peer_addr);
19257 SequencedSocketData data1(connect1, reads1, writes1);
19258 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19259
19260 AddSSLSocketData();
19261
19262 // Retry the second request on a second connection.
19263 SpdyTestUtil spdy_util2;
19264 spdy::SpdySerializedFrame req3(
19265 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
19266 MockWrite writes2[] = {
19267 CreateMockWrite(req3, 0),
19268 };
19269
19270 spdy::SpdySerializedFrame resp3(
19271 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
19272 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
19273 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
19274 MockRead(ASYNC, 0, 3)};
19275
19276 MockConnect connect2(ASYNC, OK, peer_addr);
19277 SequencedSocketData data2(connect2, reads2, writes2);
19278 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19279
19280 AddSSLSocketData();
19281
19282 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3319283 int rv = session_deps_.host_resolver->LoadIntoCache(
19284 HostPortPair("mail.example.com", 443), base::nullopt);
19285 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4219286
19287 HttpRequestInfo request1;
19288 request1.method = "GET";
19289 request1.url = GURL("https://www.example.org/");
19290 request1.load_flags = 0;
19291 request1.traffic_annotation =
19292 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19293 auto trans1 =
19294 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19295
Eric Orthf4db66a2019-02-19 21:35:3319296 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219297 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
19298 EXPECT_THAT(callback.GetResult(rv), IsOk());
19299
19300 const HttpResponseInfo* response = trans1->GetResponseInfo();
19301 ASSERT_TRUE(response);
19302 ASSERT_TRUE(response->headers);
19303 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19304 EXPECT_TRUE(response->was_fetched_via_spdy);
19305 EXPECT_TRUE(response->was_alpn_negotiated);
19306 std::string response_data;
19307 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19308 EXPECT_EQ("hello!", response_data);
19309
19310 trans1.reset();
19311
19312 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19313
19314 HttpRequestInfo request2;
19315 request2.method = "GET";
19316 request2.url = GURL("https://mail.example.org/");
19317 request2.load_flags = 0;
19318 request2.traffic_annotation =
19319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19320 auto trans2 =
19321 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19322
19323 BoundTestNetLog log;
19324 rv = trans2->Start(&request2, callback.callback(), log.bound());
19325 EXPECT_THAT(callback.GetResult(rv), IsOk());
19326
19327 response = trans2->GetResponseInfo();
19328 ASSERT_TRUE(response);
19329 ASSERT_TRUE(response->headers);
19330 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19331 EXPECT_TRUE(response->was_fetched_via_spdy);
19332 EXPECT_TRUE(response->was_alpn_negotiated);
19333 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19334 EXPECT_EQ("hello!", response_data);
19335
19336 trans2.reset();
19337
19338 // One 200 report from the first request, then a 421 report from the
19339 // second request, then a 200 report from the successful retry.
19340 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19341
19342 // Check error report contents
19343 const NetworkErrorLoggingService::RequestDetails& error1 =
19344 network_error_logging_service()->errors()[0];
19345 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
19346 EXPECT_TRUE(error1.referrer.is_empty());
19347 EXPECT_EQ("", error1.user_agent);
19348 EXPECT_EQ(ip, error1.server_ip);
19349 EXPECT_EQ("h2", error1.protocol);
19350 EXPECT_EQ("GET", error1.method);
19351 EXPECT_EQ(200, error1.status_code);
19352 EXPECT_EQ(OK, error1.type);
19353 EXPECT_EQ(0, error1.reporting_upload_depth);
19354
19355 const NetworkErrorLoggingService::RequestDetails& error2 =
19356 network_error_logging_service()->errors()[1];
19357 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
19358 EXPECT_TRUE(error2.referrer.is_empty());
19359 EXPECT_EQ("", error2.user_agent);
19360 EXPECT_EQ(ip, error2.server_ip);
19361 EXPECT_EQ("h2", error2.protocol);
19362 EXPECT_EQ("GET", error2.method);
19363 EXPECT_EQ(421, error2.status_code);
19364 EXPECT_EQ(OK, error2.type);
19365 EXPECT_EQ(0, error2.reporting_upload_depth);
19366
19367 const NetworkErrorLoggingService::RequestDetails& error3 =
19368 network_error_logging_service()->errors()[2];
19369 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
19370 EXPECT_TRUE(error3.referrer.is_empty());
19371 EXPECT_EQ("", error3.user_agent);
19372 EXPECT_EQ(ip, error3.server_ip);
19373 EXPECT_EQ("h2", error3.protocol);
19374 EXPECT_EQ("GET", error3.method);
19375 EXPECT_EQ(200, error3.status_code);
19376 EXPECT_EQ(OK, error3.type);
19377 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3619378}
19379
Lily Chend3930e72019-03-01 19:31:1119380TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19381 CreateReportCancelAfterStart) {
19382 StaticSocketDataProvider data;
19383 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
19384 session_deps_.socket_factory->AddSocketDataProvider(&data);
19385
19386 TestCompletionCallback callback;
19387 auto session = CreateSession(&session_deps_);
19388 auto trans =
19389 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19390 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19391 EXPECT_EQ(rv, ERR_IO_PENDING);
19392
19393 // Cancel after start.
19394 trans.reset();
19395
19396 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19397 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
19398 IPAddress() /* server_ip */);
19399}
19400
19401TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19402 CreateReportCancelBeforeReadingBody) {
19403 std::string extra_header_string = extra_headers_.ToString();
19404 MockWrite data_writes[] = {
19405 MockWrite("GET / HTTP/1.1\r\n"
19406 "Host: www.example.org\r\n"
19407 "Connection: keep-alive\r\n"),
19408 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19409 };
19410 MockRead data_reads[] = {
19411 MockRead("HTTP/1.0 200 OK\r\n"),
19412 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
19413 };
19414
19415 StaticSocketDataProvider data(data_reads, data_writes);
19416 session_deps_.socket_factory->AddSocketDataProvider(&data);
19417
19418 SSLSocketDataProvider ssl(ASYNC, OK);
19419 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19420
19421 TestCompletionCallback callback;
19422 auto session = CreateSession(&session_deps_);
19423 auto trans =
19424 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19425 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19426 EXPECT_THAT(callback.GetResult(rv), IsOk());
19427
19428 const HttpResponseInfo* response = trans->GetResponseInfo();
19429 ASSERT_TRUE(response);
19430
19431 EXPECT_TRUE(response->headers);
19432 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19433
19434 // Cancel before reading the body.
19435 trans.reset();
19436
19437 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19438 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
19439}
19440
Lily Chen00196ab62018-12-04 19:52:2919441TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
19442 base::HistogramTester histograms;
19443 RequestPolicy();
19444 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19445 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19446
19447 // Make HTTP request
19448 std::string extra_header_string = extra_headers_.ToString();
19449 MockRead data_reads[] = {
19450 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19451 MockRead("hello world"),
19452 MockRead(SYNCHRONOUS, OK),
19453 };
19454 MockWrite data_writes[] = {
19455 MockWrite("GET / HTTP/1.1\r\n"
19456 "Host: www.example.org\r\n"
19457 "Connection: keep-alive\r\n"),
19458 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19459 };
19460
Lily Chend3930e72019-03-01 19:31:1119461 StaticSocketDataProvider data(data_reads, data_writes);
19462 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2919463
Lily Chenfec60d92019-01-24 01:16:4219464 // Insecure url
19465 url_ = "http://www.example.org/";
19466 request_.url = GURL(url_);
19467
Lily Chen00196ab62018-12-04 19:52:2919468 TestCompletionCallback callback;
19469 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4219470 auto trans =
19471 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19472 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19473 EXPECT_THAT(callback.GetResult(rv), IsOk());
19474
19475 std::string response_data;
19476 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19477 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2919478
19479 // Insecure request does not generate a report
19480 histograms.ExpectBucketCount(
19481 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519482 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919483
19484 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19485}
19486
19487TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19488 DontCreateReportHttpError) {
19489 base::HistogramTester histograms;
19490 RequestPolicy();
19491 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19492 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19493
19494 // Make HTTP request that fails
19495 MockRead data_reads[] = {
19496 MockRead("hello world"),
19497 MockRead(SYNCHRONOUS, OK),
19498 };
19499
19500 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19501 session_deps_.socket_factory->AddSocketDataProvider(&data);
19502
Lily Chenfec60d92019-01-24 01:16:4219503 url_ = "http://www.originwithoutpolicy.com:2000/";
19504 request_.url = GURL(url_);
19505
Lily Chen00196ab62018-12-04 19:52:2919506 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19507
Lily Chen00196ab62018-12-04 19:52:2919508 auto trans =
19509 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2919510 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219511 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2919512 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
19513
19514 // Insecure request does not generate a report, regardless of existence of a
19515 // policy for the origin.
19516 histograms.ExpectBucketCount(
19517 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519518 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919519
19520 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19521}
19522
Lily Chen90ae93cc2019-02-14 01:15:3919523// Don't report on proxy auth challenges, don't report if connecting through a
19524// proxy.
19525TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
19526 HttpRequestInfo request;
19527 request.method = "GET";
19528 request.url = GURL("https://www.example.org/");
19529 request.traffic_annotation =
19530 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19531
19532 // Configure against proxy server "myproxy:70".
19533 session_deps_.proxy_resolution_service =
19534 ProxyResolutionService::CreateFixedFromPacResult(
19535 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19536 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19537
19538 // Since we have proxy, should try to establish tunnel.
19539 MockWrite data_writes1[] = {
19540 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19541 "Host: www.example.org:443\r\n"
19542 "Proxy-Connection: keep-alive\r\n\r\n"),
19543 };
19544
19545 // The proxy responds to the connect with a 407, using a non-persistent
19546 // connection.
19547 MockRead data_reads1[] = {
19548 // No credentials.
19549 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
19550 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19551 MockRead("Proxy-Connection: close\r\n\r\n"),
19552 };
19553
19554 MockWrite data_writes2[] = {
19555 // After calling trans->RestartWithAuth(), this is the request we should
19556 // be issuing -- the final header line contains the credentials.
19557 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19558 "Host: www.example.org:443\r\n"
19559 "Proxy-Connection: keep-alive\r\n"
19560 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
19561
19562 MockWrite("GET / HTTP/1.1\r\n"
19563 "Host: www.example.org\r\n"
19564 "Connection: keep-alive\r\n\r\n"),
19565 };
19566
19567 MockRead data_reads2[] = {
19568 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19569
19570 MockRead("HTTP/1.1 200 OK\r\n"),
19571 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19572 MockRead("Content-Length: 5\r\n\r\n"),
19573 MockRead(SYNCHRONOUS, "hello"),
19574 };
19575
19576 StaticSocketDataProvider data1(data_reads1, data_writes1);
19577 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19578 StaticSocketDataProvider data2(data_reads2, data_writes2);
19579 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19580 SSLSocketDataProvider ssl(ASYNC, OK);
19581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19582
19583 TestCompletionCallback callback1;
19584
19585 auto trans =
19586 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19587
19588 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
19589 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19590
19591 const HttpResponseInfo* response = trans->GetResponseInfo();
19592 EXPECT_EQ(407, response->headers->response_code());
19593
19594 std::string response_data;
19595 rv = ReadTransaction(trans.get(), &response_data);
19596 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
19597
19598 // No NEL report is generated for the 407.
19599 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19600
19601 TestCompletionCallback callback2;
19602
19603 rv =
19604 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19605 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19606
19607 response = trans->GetResponseInfo();
19608 EXPECT_EQ(200, response->headers->response_code());
19609
19610 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19611 EXPECT_EQ("hello", response_data);
19612
19613 trans.reset();
19614
19615 // No NEL report is generated because we are behind a proxy.
19616 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19617}
19618
Douglas Creageref5eecdc2018-11-09 20:50:3619619TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19620 ReportContainsUploadDepth) {
19621 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4219622 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3619623 RequestPolicy();
19624 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219625 const NetworkErrorLoggingService::RequestDetails& error =
19626 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3619627 EXPECT_EQ(7, error.reporting_upload_depth);
19628}
19629
Lily Chenfec60d92019-01-24 01:16:4219630TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
19631 std::string extra_header_string = extra_headers_.ToString();
19632 static const base::TimeDelta kSleepDuration =
19633 base::TimeDelta::FromMilliseconds(10);
19634
19635 std::vector<MockWrite> data_writes = {
19636 MockWrite(ASYNC, 0,
19637 "GET / HTTP/1.1\r\n"
19638 "Host: www.example.org\r\n"
19639 "Connection: keep-alive\r\n"),
19640 MockWrite(ASYNC, 1, extra_header_string.data()),
19641 };
19642
19643 std::vector<MockRead> data_reads = {
19644 // Write one byte of the status line, followed by a pause.
19645 MockRead(ASYNC, 2, "H"),
19646 MockRead(ASYNC, ERR_IO_PENDING, 3),
19647 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
19648 MockRead(ASYNC, 5, "hello world"),
19649 MockRead(SYNCHRONOUS, OK, 6),
19650 };
19651
19652 SequencedSocketData data(data_reads, data_writes);
19653 session_deps_.socket_factory->AddSocketDataProvider(&data);
19654
19655 SSLSocketDataProvider ssl(ASYNC, OK);
19656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19657
19658 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19659
19660 auto trans =
19661 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19662
19663 TestCompletionCallback callback;
19664
19665 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19666 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19667
19668 data.RunUntilPaused();
19669 ASSERT_TRUE(data.IsPaused());
19670 FastForwardBy(kSleepDuration);
19671 data.Resume();
19672
19673 EXPECT_THAT(callback.GetResult(rv), IsOk());
19674
19675 std::string response_data;
19676 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19677 EXPECT_EQ("hello world", response_data);
19678
19679 trans.reset();
19680
Douglas Creageref5eecdc2018-11-09 20:50:3619681 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219682
19683 CheckReport(0 /* index */, 200 /* status_code */, OK);
19684
19685 const NetworkErrorLoggingService::RequestDetails& error =
19686 network_error_logging_service()->errors()[0];
19687
19688 // Sanity-check elapsed time in error report
19689 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3619690}
Lily Chenfec60d92019-01-24 01:16:4219691
Douglas Creager3cb042052018-11-06 23:08:5219692#endif // BUILDFLAG(ENABLE_REPORTING)
19693
Batalov Vladislava4e97a502019-04-11 15:35:2319694TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
19695 HttpRequestInfo request;
19696 request.method = "GET";
19697 request.url = GURL("http://example.org/");
19698
19699 request.load_flags = LOAD_ONLY_FROM_CACHE;
19700
19701 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19702 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19703 TestCompletionCallback callback1;
19704 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
19705
19706 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
19707}
19708
Steven Valdez1c1859172019-04-10 15:33:2819709TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
19710 HttpRequestInfo request;
19711 request.method = "GET";
19712 request.url = GURL("https://www.example.org/");
19713 request.traffic_annotation =
19714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19715
19716 MockWrite data_writes[] = {
19717 MockWrite("GET / HTTP/1.1\r\n"
19718 "Host: www.example.org\r\n"
19719 "Connection: keep-alive\r\n\r\n"),
19720 };
19721
19722 // The proxy responds to the connect with a 407, using a persistent
19723 // connection.
19724 MockRead data_reads[] = {
19725 MockRead("HTTP/1.1 200 OK\r\n"),
19726 MockRead("Content-Length: 1\r\n\r\n"),
19727 MockRead(SYNCHRONOUS, "1"),
19728 };
19729
19730 StaticSocketDataProvider data(data_reads, data_writes);
19731 session_deps_.socket_factory->AddSocketDataProvider(&data);
19732 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19733 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19734 session_deps_.enable_early_data = true;
19735 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19736
19737 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19738
19739 TestCompletionCallback callback;
19740 auto trans =
19741 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19742
19743 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19744 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19745
19746 rv = callback.WaitForResult();
19747 EXPECT_THAT(rv, IsOk());
19748
19749 const HttpResponseInfo* response = trans->GetResponseInfo();
19750 ASSERT_TRUE(response);
19751 ASSERT_TRUE(response->headers);
19752 EXPECT_EQ(200, response->headers->response_code());
19753 EXPECT_EQ(1, response->headers->GetContentLength());
19754
19755 // Check that ConfirmHandshake wasn't called.
19756 ASSERT_FALSE(ssl.ConfirmDataConsumed());
19757 ASSERT_TRUE(ssl.WriteBeforeConfirm());
19758
19759 trans.reset();
19760
19761 session->CloseAllConnections();
19762}
19763
19764TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
19765 HttpRequestInfo request;
19766 request.method = "POST";
19767 request.url = GURL("https://www.example.org/");
19768 request.traffic_annotation =
19769 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19770
19771 MockWrite data_writes[] = {
19772 MockWrite(SYNCHRONOUS,
19773 "POST / HTTP/1.1\r\n"
19774 "Host: www.example.org\r\n"
19775 "Connection: keep-alive\r\n"
19776 "Content-Length: 0\r\n\r\n"),
19777 };
19778
19779 // The proxy responds to the connect with a 407, using a persistent
19780 // connection.
19781 MockRead data_reads[] = {
19782 MockRead("HTTP/1.1 200 OK\r\n"),
19783 MockRead("Content-Length: 1\r\n\r\n"),
19784 MockRead(SYNCHRONOUS, "1"),
19785 };
19786
19787 StaticSocketDataProvider data(data_reads, data_writes);
19788 session_deps_.socket_factory->AddSocketDataProvider(&data);
19789 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19790 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19791 session_deps_.enable_early_data = true;
19792 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19793
19794 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19795
19796 TestCompletionCallback callback;
19797 auto trans =
19798 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19799
19800 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19801 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19802
19803 rv = callback.WaitForResult();
19804 EXPECT_THAT(rv, IsOk());
19805
19806 const HttpResponseInfo* response = trans->GetResponseInfo();
19807 ASSERT_TRUE(response);
19808 ASSERT_TRUE(response->headers);
19809 EXPECT_EQ(200, response->headers->response_code());
19810 EXPECT_EQ(1, response->headers->GetContentLength());
19811
19812 // Check that the Write didn't get called before ConfirmHandshake completed.
19813 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19814
19815 trans.reset();
19816
19817 session->CloseAllConnections();
19818}
19819
19820TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
19821 HttpRequestInfo request;
19822 request.method = "POST";
19823 request.url = GURL("https://www.example.org/");
19824 request.traffic_annotation =
19825 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19826
19827 MockWrite data_writes[] = {
19828 MockWrite(ASYNC,
19829 "POST / HTTP/1.1\r\n"
19830 "Host: www.example.org\r\n"
19831 "Connection: keep-alive\r\n"
19832 "Content-Length: 0\r\n\r\n"),
19833 };
19834
19835 // The proxy responds to the connect with a 407, using a persistent
19836 // connection.
19837 MockRead data_reads[] = {
19838 MockRead("HTTP/1.1 200 OK\r\n"),
19839 MockRead("Content-Length: 1\r\n\r\n"),
19840 MockRead(SYNCHRONOUS, "1"),
19841 };
19842
19843 StaticSocketDataProvider data(data_reads, data_writes);
19844 session_deps_.socket_factory->AddSocketDataProvider(&data);
19845 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19846 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19847 session_deps_.enable_early_data = true;
19848 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19849
19850 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19851
19852 TestCompletionCallback callback;
19853 auto trans =
19854 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19855
19856 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19857 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19858
19859 rv = callback.WaitForResult();
19860 EXPECT_THAT(rv, IsOk());
19861
19862 const HttpResponseInfo* response = trans->GetResponseInfo();
19863 ASSERT_TRUE(response);
19864 ASSERT_TRUE(response->headers);
19865 EXPECT_EQ(200, response->headers->response_code());
19866 EXPECT_EQ(1, response->headers->GetContentLength());
19867
19868 // Check that the Write didn't get called before ConfirmHandshake completed.
19869 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19870
19871 trans.reset();
19872
19873 session->CloseAllConnections();
19874}
19875
19876TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
19877 HttpRequestInfo request;
19878 request.method = "POST";
19879 request.url = GURL("https://www.example.org/");
19880 request.traffic_annotation =
19881 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19882
19883 MockWrite data_writes[] = {
19884 MockWrite(SYNCHRONOUS,
19885 "POST / HTTP/1.1\r\n"
19886 "Host: www.example.org\r\n"
19887 "Connection: keep-alive\r\n"
19888 "Content-Length: 0\r\n\r\n"),
19889 };
19890
19891 // The proxy responds to the connect with a 407, using a persistent
19892 // connection.
19893 MockRead data_reads[] = {
19894 MockRead("HTTP/1.1 200 OK\r\n"),
19895 MockRead("Content-Length: 1\r\n\r\n"),
19896 MockRead(SYNCHRONOUS, "1"),
19897 };
19898
19899 StaticSocketDataProvider data(data_reads, data_writes);
19900 session_deps_.socket_factory->AddSocketDataProvider(&data);
19901 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19902 ssl.confirm = MockConfirm(ASYNC, OK);
19903 session_deps_.enable_early_data = true;
19904 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19905
19906 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19907
19908 TestCompletionCallback callback;
19909 auto trans =
19910 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19911
19912 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19913 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19914
19915 rv = callback.WaitForResult();
19916 EXPECT_THAT(rv, IsOk());
19917
19918 const HttpResponseInfo* response = trans->GetResponseInfo();
19919 ASSERT_TRUE(response);
19920 ASSERT_TRUE(response->headers);
19921 EXPECT_EQ(200, response->headers->response_code());
19922 EXPECT_EQ(1, response->headers->GetContentLength());
19923
19924 // Check that the Write didn't get called before ConfirmHandshake completed.
19925 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19926
19927 trans.reset();
19928
19929 session->CloseAllConnections();
19930}
19931
19932TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
19933 HttpRequestInfo request;
19934 request.method = "POST";
19935 request.url = GURL("https://www.example.org/");
19936 request.traffic_annotation =
19937 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19938
19939 MockWrite data_writes[] = {
19940 MockWrite(ASYNC,
19941 "POST / HTTP/1.1\r\n"
19942 "Host: www.example.org\r\n"
19943 "Connection: keep-alive\r\n"
19944 "Content-Length: 0\r\n\r\n"),
19945 };
19946
19947 // The proxy responds to the connect with a 407, using a persistent
19948 // connection.
19949 MockRead data_reads[] = {
19950 MockRead("HTTP/1.1 200 OK\r\n"),
19951 MockRead("Content-Length: 1\r\n\r\n"),
19952 MockRead(SYNCHRONOUS, "1"),
19953 };
19954
19955 StaticSocketDataProvider data(data_reads, data_writes);
19956 session_deps_.socket_factory->AddSocketDataProvider(&data);
19957 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19958 ssl.confirm = MockConfirm(ASYNC, OK);
19959 session_deps_.enable_early_data = true;
19960 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19961
19962 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19963
19964 TestCompletionCallback callback;
19965 auto trans =
19966 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19967
19968 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19969 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19970
19971 rv = callback.WaitForResult();
19972 EXPECT_THAT(rv, IsOk());
19973
19974 const HttpResponseInfo* response = trans->GetResponseInfo();
19975 ASSERT_TRUE(response);
19976 ASSERT_TRUE(response->headers);
19977 EXPECT_EQ(200, response->headers->response_code());
19978 EXPECT_EQ(1, response->headers->GetContentLength());
19979
19980 // Check that the Write didn't get called before ConfirmHandshake completed.
19981 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19982
19983 trans.reset();
19984
19985 session->CloseAllConnections();
19986}
19987
19988TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
19989 HttpRequestInfo request;
19990 request.method = "POST";
19991 request.url = GURL("https://www.example.org/");
19992 request.traffic_annotation =
19993 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19994
19995 MockWrite data_writes[] = {
19996 MockWrite("POST / HTTP/1.1\r\n"
19997 "Host: www.example.org\r\n"
19998 "Connection: keep-alive\r\n"
19999 "Content-Length: 0\r\n\r\n"),
20000 };
20001
20002 // The proxy responds to the connect with a 407, using a persistent
20003 // connection.
20004 MockRead data_reads[] = {
20005 MockRead("HTTP/1.1 200 OK\r\n"),
20006 MockRead("Content-Length: 1\r\n\r\n"),
20007 MockRead(SYNCHRONOUS, "1"),
20008 };
20009
20010 StaticSocketDataProvider data(data_reads, data_writes);
20011 session_deps_.socket_factory->AddSocketDataProvider(&data);
20012 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20013 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
20014 session_deps_.enable_early_data = true;
20015 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20016
20017 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20018
20019 TestCompletionCallback callback;
20020 auto trans =
20021 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20022
20023 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20024 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20025
20026 rv = callback.WaitForResult();
20027 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20028
20029 // Check that the Write didn't get called before ConfirmHandshake completed.
20030 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20031
20032 trans.reset();
20033
20034 session->CloseAllConnections();
20035}
20036
20037TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
20038 HttpRequestInfo request;
20039 request.method = "POST";
20040 request.url = GURL("https://www.example.org/");
20041 request.traffic_annotation =
20042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20043
20044 MockWrite data_writes[] = {
20045 MockWrite("POST / HTTP/1.1\r\n"
20046 "Host: www.example.org\r\n"
20047 "Connection: keep-alive\r\n"
20048 "Content-Length: 0\r\n\r\n"),
20049 };
20050
20051 // The proxy responds to the connect with a 407, using a persistent
20052 // connection.
20053 MockRead data_reads[] = {
20054 MockRead("HTTP/1.1 200 OK\r\n"),
20055 MockRead("Content-Length: 1\r\n\r\n"),
20056 MockRead(SYNCHRONOUS, "1"),
20057 };
20058
20059 StaticSocketDataProvider data(data_reads, data_writes);
20060 session_deps_.socket_factory->AddSocketDataProvider(&data);
20061 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20062 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
20063 session_deps_.enable_early_data = true;
20064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20065
20066 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20067
20068 TestCompletionCallback callback;
20069 auto trans =
20070 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20071
20072 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20073 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20074
20075 rv = callback.WaitForResult();
20076 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20077
20078 // Check that the Write didn't get called before ConfirmHandshake completed.
20079 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20080
20081 trans.reset();
20082
20083 session->CloseAllConnections();
20084}
20085
David Benjamin2eb827f2019-04-29 18:31:0420086// Test the proxy and origin server each requesting both TLS client certificates
20087// and HTTP auth. This is a regression test for https://crbug.com/946406.
20088TEST_F(HttpNetworkTransactionTest, AuthEverything) {
20089 // Note these hosts must match the CheckBasic*Auth() functions.
20090 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20091 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20092
20093 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20094 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20095
20096 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20097 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20098 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20099 ASSERT_TRUE(identity_proxy);
20100
20101 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20102 cert_request_info_origin->host_and_port =
20103 HostPortPair("www.example.org", 443);
20104
20105 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20106 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20107 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20108 ASSERT_TRUE(identity_origin);
20109
20110 HttpRequestInfo request;
20111 request.method = "GET";
20112 request.url = GURL("https://www.example.org/");
20113 request.traffic_annotation =
20114 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20115
David Benjamin7ebab032019-04-30 21:51:3020116 // First, the client connects to the proxy, which requests a client
20117 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420118 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20119 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20120 ssl_proxy1.expected_send_client_cert = false;
David Benjamin21df4d52019-04-30 22:36:5920121 ssl_proxy1.expected_false_start_enabled = true;
David Benjamin2eb827f2019-04-29 18:31:0420122 StaticSocketDataProvider data1;
20123 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020124 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420125
David Benjamin7ebab032019-04-30 21:51:3020126 // The client responds with a certificate on a new connection. The handshake
20127 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420128 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20129 ssl_proxy2.expected_send_client_cert = true;
20130 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin21df4d52019-04-30 22:36:5920131 // Proxy connections with client certs disable False Start.
20132 ssl_proxy2.expected_false_start_enabled = false;
David Benjamin7ebab032019-04-30 21:51:3020133 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420134 std::vector<MockWrite> mock_writes2;
20135 std::vector<MockRead> mock_reads2;
20136 mock_writes2.emplace_back(
20137 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20138 "Host: www.example.org:443\r\n"
20139 "Proxy-Connection: keep-alive\r\n\r\n");
20140 mock_reads2.emplace_back(
20141 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20142 "Content-Length: 0\r\n"
20143 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020144 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0420145 mock_writes2.emplace_back(
20146 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20147 "Host: www.example.org:443\r\n"
20148 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020149 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420150 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20151 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20152 // The origin requests client certificates.
20153 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20154 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin21df4d52019-04-30 22:36:5920155 // The origin connection is eligible for False Start, despite the proxy
20156 // connection disabling it.
20157 ssl_origin2.expected_false_start_enabled = true;
David Benjamin2eb827f2019-04-29 18:31:0420158 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20159 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20161 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0420162
David Benjamin7ebab032019-04-30 21:51:3020163 // The client responds to the origin client certificate request on a new
20164 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420165 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20166 ssl_proxy3.expected_send_client_cert = true;
20167 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin21df4d52019-04-30 22:36:5920168 // Proxy connections with client certs disable False Start.
20169 ssl_proxy3.expected_false_start_enabled = false;
David Benjamin2eb827f2019-04-29 18:31:0420170 std::vector<MockWrite> mock_writes3;
20171 std::vector<MockRead> mock_reads3;
20172 mock_writes3.emplace_back(
20173 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20174 "Host: www.example.org:443\r\n"
20175 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020176 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420177 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20178 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20179 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
20180 ssl_origin3.expected_send_client_cert = true;
20181 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin21df4d52019-04-30 22:36:5920182 // The origin connection is eligible for False Start, despite the proxy
20183 // connection disabling it.
20184 ssl_origin3.expected_false_start_enabled = true;
David Benjamin7ebab032019-04-30 21:51:3020185 // The client sends the origin HTTP request, which results in another HTTP
20186 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0420187 mock_writes3.emplace_back(
20188 "GET / HTTP/1.1\r\n"
20189 "Host: www.example.org\r\n"
20190 "Connection: keep-alive\r\n\r\n");
20191 mock_reads3.emplace_back(
20192 "HTTP/1.1 401 Unauthorized\r\n"
20193 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20194 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020195 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420196 mock_writes3.emplace_back(
20197 "GET / HTTP/1.1\r\n"
20198 "Host: www.example.org\r\n"
20199 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020200 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420201 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20202 mock_reads3.emplace_back(
20203 "HTTP/1.1 200 OK\r\n"
20204 "Content-Length: 0\r\n\r\n");
20205 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20206 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020207 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20208 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420209
20210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20211
20212 // Start the request.
20213 TestCompletionCallback callback;
20214 auto trans =
20215 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20216 int rv = callback.GetResult(
20217 trans->Start(&request, callback.callback(), NetLogWithSource()));
20218
20219 // Handle the proxy client certificate challenge.
20220 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20221 SSLCertRequestInfo* cert_request_info =
20222 trans->GetResponseInfo()->cert_request_info.get();
20223 ASSERT_TRUE(cert_request_info);
20224 EXPECT_TRUE(cert_request_info->is_proxy);
20225 EXPECT_EQ(cert_request_info->host_and_port,
20226 cert_request_info_proxy->host_and_port);
20227 rv = callback.GetResult(trans->RestartWithCertificate(
20228 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20229 callback.callback()));
20230
20231 // Handle the proxy HTTP auth challenge.
20232 ASSERT_THAT(rv, IsOk());
20233 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20234 EXPECT_TRUE(
20235 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20236 rv = callback.GetResult(trans->RestartWithAuth(
20237 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20238 callback.callback()));
20239
20240 // Handle the origin client certificate challenge.
20241 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20242 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20243 ASSERT_TRUE(cert_request_info);
20244 EXPECT_FALSE(cert_request_info->is_proxy);
20245 EXPECT_EQ(cert_request_info->host_and_port,
20246 cert_request_info_origin->host_and_port);
20247 rv = callback.GetResult(trans->RestartWithCertificate(
20248 identity_origin->certificate(), identity_origin->ssl_private_key(),
20249 callback.callback()));
20250
20251 // Handle the origin HTTP auth challenge.
20252 ASSERT_THAT(rv, IsOk());
20253 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20254 EXPECT_TRUE(
20255 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20256 rv = callback.GetResult(trans->RestartWithAuth(
20257 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20258 callback.callback()));
20259
20260 // The request completes.
20261 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020262 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420263}
20264
20265// Test the proxy and origin server each requesting both TLS client certificates
20266// and HTTP auth and each HTTP auth closing the connection. This is a regression
20267// test for https://crbug.com/946406.
20268TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
20269 // Note these hosts must match the CheckBasic*Auth() functions.
20270 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20271 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20272
20273 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20274 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20275
20276 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20277 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20278 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20279 ASSERT_TRUE(identity_proxy);
20280
20281 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20282 cert_request_info_origin->host_and_port =
20283 HostPortPair("www.example.org", 443);
20284
20285 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20286 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20287 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20288 ASSERT_TRUE(identity_origin);
20289
20290 HttpRequestInfo request;
20291 request.method = "GET";
20292 request.url = GURL("https://www.example.org/");
20293 request.traffic_annotation =
20294 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20295
David Benjamin7ebab032019-04-30 21:51:3020296 // First, the client connects to the proxy, which requests a client
20297 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420298 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20299 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20300 ssl_proxy1.expected_send_client_cert = false;
20301 StaticSocketDataProvider data1;
20302 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020303 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420304
David Benjamin7ebab032019-04-30 21:51:3020305 // The client responds with a certificate on a new connection. The handshake
20306 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420307 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20308 ssl_proxy2.expected_send_client_cert = true;
20309 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020310 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420311 std::vector<MockWrite> mock_writes2;
20312 std::vector<MockRead> mock_reads2;
20313 mock_writes2.emplace_back(
20314 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20315 "Host: www.example.org:443\r\n"
20316 "Proxy-Connection: keep-alive\r\n\r\n");
20317 mock_reads2.emplace_back(
20318 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20319 "Content-Length: 0\r\n"
20320 "Proxy-Connection: close\r\n"
20321 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20322 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20323 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020324 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0420325
David Benjamin7ebab032019-04-30 21:51:3020326 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0420327 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20328 ssl_proxy3.expected_send_client_cert = true;
20329 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20330 std::vector<MockWrite> mock_writes3;
20331 std::vector<MockRead> mock_reads3;
20332 mock_writes3.emplace_back(
20333 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20334 "Host: www.example.org:443\r\n"
20335 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020336 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420337 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20338 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20339 // The origin requests client certificates.
20340 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20341 ssl_origin3.cert_request_info = cert_request_info_origin.get();
20342 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20343 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020344 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20345 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420346
David Benjamin7ebab032019-04-30 21:51:3020347 // The client responds to the origin client certificate request on a new
20348 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420349 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
20350 ssl_proxy4.expected_send_client_cert = true;
20351 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
20352 std::vector<MockWrite> mock_writes4;
20353 std::vector<MockRead> mock_reads4;
20354 mock_writes4.emplace_back(
20355 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20356 "Host: www.example.org:443\r\n"
20357 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020358 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420359 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20360 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20361 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
20362 ssl_origin4.expected_send_client_cert = true;
20363 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020364 // The client sends the origin HTTP request, which results in another HTTP
20365 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0420366 mock_writes4.emplace_back(
20367 "GET / HTTP/1.1\r\n"
20368 "Host: www.example.org\r\n"
20369 "Connection: keep-alive\r\n\r\n");
20370 mock_reads4.emplace_back(
20371 "HTTP/1.1 401 Unauthorized\r\n"
20372 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20373 "Connection: close\r\n"
20374 "Content-Length: 0\r\n\r\n");
20375 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
20376 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3020377 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
20378 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0420379
David Benjamin7ebab032019-04-30 21:51:3020380 // The client retries with credentials on a new connection, and the request
20381 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420382 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
20383 ssl_proxy5.expected_send_client_cert = true;
20384 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
20385 std::vector<MockWrite> mock_writes5;
20386 std::vector<MockRead> mock_reads5;
20387 mock_writes5.emplace_back(
20388 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20389 "Host: www.example.org:443\r\n"
20390 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020391 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420392 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20393 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20394 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
20395 ssl_origin5.expected_send_client_cert = true;
20396 ssl_origin5.expected_client_cert = identity_origin->certificate();
20397 mock_writes5.emplace_back(
20398 "GET / HTTP/1.1\r\n"
20399 "Host: www.example.org\r\n"
20400 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020401 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420402 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20403 mock_reads5.emplace_back(
20404 "HTTP/1.1 200 OK\r\n"
20405 "Connection: close\r\n"
20406 "Content-Length: 0\r\n\r\n");
20407 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
20408 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3020409 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
20410 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0420411
20412 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20413
20414 // Start the request.
20415 TestCompletionCallback callback;
20416 auto trans =
20417 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20418 int rv = callback.GetResult(
20419 trans->Start(&request, callback.callback(), NetLogWithSource()));
20420
20421 // Handle the proxy client certificate challenge.
20422 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20423 SSLCertRequestInfo* cert_request_info =
20424 trans->GetResponseInfo()->cert_request_info.get();
20425 ASSERT_TRUE(cert_request_info);
20426 EXPECT_TRUE(cert_request_info->is_proxy);
20427 EXPECT_EQ(cert_request_info->host_and_port,
20428 cert_request_info_proxy->host_and_port);
20429 rv = callback.GetResult(trans->RestartWithCertificate(
20430 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20431 callback.callback()));
20432
20433 // Handle the proxy HTTP auth challenge.
20434 ASSERT_THAT(rv, IsOk());
20435 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20436 EXPECT_TRUE(
20437 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20438 rv = callback.GetResult(trans->RestartWithAuth(
20439 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20440 callback.callback()));
20441
20442 // Handle the origin client certificate challenge.
20443 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20444 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20445 ASSERT_TRUE(cert_request_info);
20446 EXPECT_FALSE(cert_request_info->is_proxy);
20447 EXPECT_EQ(cert_request_info->host_and_port,
20448 cert_request_info_origin->host_and_port);
20449 rv = callback.GetResult(trans->RestartWithCertificate(
20450 identity_origin->certificate(), identity_origin->ssl_private_key(),
20451 callback.callback()));
20452
20453 // Handle the origin HTTP auth challenge.
20454 ASSERT_THAT(rv, IsOk());
20455 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20456 EXPECT_TRUE(
20457 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20458 rv = callback.GetResult(trans->RestartWithAuth(
20459 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20460 callback.callback()));
20461
20462 // The request completes.
20463 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020464 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20465}
20466
20467// Test the proxy requesting HTTP auth and the server requesting TLS client
20468// certificates. This is a regression test for https://crbug.com/946406.
20469TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
20470 // Note these hosts must match the CheckBasic*Auth() functions.
20471 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20472 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20473
20474 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20475 cert_request_info_origin->host_and_port =
20476 HostPortPair("www.example.org", 443);
20477
20478 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20479 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20480 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20481 ASSERT_TRUE(identity_origin);
20482
20483 HttpRequestInfo request;
20484 request.method = "GET";
20485 request.url = GURL("https://www.example.org/");
20486 request.traffic_annotation =
20487 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20488
20489 // The client connects to the proxy. The handshake succeeds.
20490 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
20491 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20492 std::vector<MockWrite> mock_writes1;
20493 std::vector<MockRead> mock_reads1;
20494 mock_writes1.emplace_back(
20495 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20496 "Host: www.example.org:443\r\n"
20497 "Proxy-Connection: keep-alive\r\n\r\n");
20498 mock_reads1.emplace_back(
20499 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20500 "Content-Length: 0\r\n"
20501 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20502 // The client retries with credentials, and the request finally succeeds.
20503 mock_writes1.emplace_back(
20504 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20505 "Host: www.example.org:443\r\n"
20506 "Proxy-Connection: keep-alive\r\n"
20507 // Authenticate as proxyuser:proxypass.
20508 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20509 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20510 // The origin requests client certificates.
20511 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20512 ssl_origin1.cert_request_info = cert_request_info_origin.get();
20513 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
20514 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
20517
20518 // The client responds to the origin client certificate request on a new
20519 // connection.
20520 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20521 std::vector<MockWrite> mock_writes2;
20522 std::vector<MockRead> mock_reads2;
20523 mock_writes2.emplace_back(
20524 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20525 "Host: www.example.org:443\r\n"
20526 "Proxy-Connection: keep-alive\r\n"
20527 // Authenticate as proxyuser:proxypass.
20528 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20529 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20530 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
20531 ssl_origin2.expected_send_client_cert = true;
20532 ssl_origin2.expected_client_cert = identity_origin->certificate();
20533 // The client sends the origin HTTP request, which succeeds.
20534 mock_writes2.emplace_back(
20535 "GET / HTTP/1.1\r\n"
20536 "Host: www.example.org\r\n"
20537 "Connection: keep-alive\r\n\r\n");
20538 mock_reads2.emplace_back(
20539 "HTTP/1.1 200 OK\r\n"
20540 "Content-Length: 0\r\n\r\n");
20541 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20542 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20543 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20544 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
20545
20546 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20547
20548 // Start the request.
20549 TestCompletionCallback callback;
20550 auto trans =
20551 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20552 int rv = callback.GetResult(
20553 trans->Start(&request, callback.callback(), NetLogWithSource()));
20554
20555 // Handle the proxy HTTP auth challenge.
20556 ASSERT_THAT(rv, IsOk());
20557 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20558 EXPECT_TRUE(
20559 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20560 rv = callback.GetResult(trans->RestartWithAuth(
20561 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20562 callback.callback()));
20563
20564 // Handle the origin client certificate challenge.
20565 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20566 SSLCertRequestInfo* cert_request_info =
20567 trans->GetResponseInfo()->cert_request_info.get();
20568 ASSERT_TRUE(cert_request_info);
20569 EXPECT_FALSE(cert_request_info->is_proxy);
20570 EXPECT_EQ(cert_request_info->host_and_port,
20571 cert_request_info_origin->host_and_port);
20572 rv = callback.GetResult(trans->RestartWithCertificate(
20573 identity_origin->certificate(), identity_origin->ssl_private_key(),
20574 callback.callback()));
20575
20576 // The request completes.
20577 ASSERT_THAT(rv, IsOk());
20578 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420579}
20580
David Benjamin6e673a82019-04-30 22:52:5820581// Test that socket reuse works with client certificates.
20582TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
20583 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
20584 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
20585
20586 std::unique_ptr<FakeClientCertIdentity> identity =
20587 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20588 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20589 ASSERT_TRUE(identity);
20590
20591 HttpRequestInfo request1;
20592 request1.method = "GET";
20593 request1.url = GURL("https://www.example.org/a");
20594 request1.traffic_annotation =
20595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20596
20597 HttpRequestInfo request2;
20598 request2.method = "GET";
20599 request2.url = GURL("https://www.example.org/b");
20600 request2.traffic_annotation =
20601 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20602
20603 // The first connection results in a client certificate request.
20604 StaticSocketDataProvider data1;
20605 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20606 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20607 ssl1.cert_request_info = cert_request_info.get();
20608 ssl1.expected_send_client_cert = false;
20609 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20610
20611 // The second connection succeeds and is usable for both requests.
20612 MockWrite mock_writes[] = {
20613 MockWrite("GET /a HTTP/1.1\r\n"
20614 "Host: www.example.org\r\n"
20615 "Connection: keep-alive\r\n\r\n"),
20616 MockWrite("GET /b HTTP/1.1\r\n"
20617 "Host: www.example.org\r\n"
20618 "Connection: keep-alive\r\n\r\n"),
20619 };
20620 MockRead mock_reads[] = {
20621 MockRead("HTTP/1.1 200 OK\r\n"
20622 "Content-Length: 0\r\n\r\n"),
20623 MockRead("HTTP/1.1 200 OK\r\n"
20624 "Content-Length: 0\r\n\r\n"),
20625 };
20626 StaticSocketDataProvider data2(mock_reads, mock_writes);
20627 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20628 SSLSocketDataProvider ssl2(ASYNC, OK);
20629 ssl2.expected_send_client_cert = true;
20630 ssl2.expected_client_cert = identity->certificate();
20631 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20632
20633 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20634
20635 // Start the first request. It succeeds after providing client certificates.
20636 TestCompletionCallback callback;
20637 auto trans =
20638 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20639 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
20640 NetLogWithSource())),
20641 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20642
20643 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
20644 ASSERT_TRUE(info);
20645 EXPECT_FALSE(info->is_proxy);
20646 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
20647
20648 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
20649 identity->certificate(), identity->ssl_private_key(),
20650 callback.callback())),
20651 IsOk());
20652 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20653
20654 // Make the second request. It completes without requesting client
20655 // certificates.
20656 trans =
20657 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20658 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
20659 NetLogWithSource())),
20660 IsOk());
20661 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20662}
20663
[email protected]89ceba9a2009-03-21 03:46:0620664} // namespace net