blob: 3aefbfcd074a586daac1510d89553fce761c827d [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"
[email protected]277d5942010-08-11 21:02:3538#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0739#include "net/base/chunked_upload_data_stream.h"
Bence Békya25e3f72018-02-13 21:13:3940#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0741#include "net/base/elements_upload_data_stream.h"
Eric Orthf4db66a2019-02-19 21:35:3342#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3743#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2544#include "net/base/load_timing_info.h"
45#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2446#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5947#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1548#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4049#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3150#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5251#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1552#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0653#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2154#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0855#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1156#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5357#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2458#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1259#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0060#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2961#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1962#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5763#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5264#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5665#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0466#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2467#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1368#include "net/http/http_response_info.h"
[email protected]17291a022011-10-10 07:32:5369#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5770#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3871#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1972#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0773#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0074#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1975#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5176#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4677#include "net/log/test_net_log_entry.h"
78#include "net/log/test_net_log_util.h"
Lily Houghton582d4622018-01-22 22:43:4079#include "net/proxy_resolution/mock_proxy_resolver.h"
80#include "net/proxy_resolution/proxy_config_service_fixed.h"
81#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0382#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4083#include "net/proxy_resolution/proxy_resolver.h"
84#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4485#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1586#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0387#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3688#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4789#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0290#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0791#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0492#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4493#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1294#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4495#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:5896#include "net/spdy/spdy_session.h"
97#include "net/spdy/spdy_session_pool.h"
98#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:0499#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57100#include "net/ssl/ssl_cert_request_info.h"
[email protected]e86839fd2013-08-14 18:29:03101#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57102#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54103#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:11104#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01105#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43106#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:01107#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14108#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23109#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00110#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44111#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06112#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18113#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52114#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15115#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27116#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52117
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37118#if defined(NTLM_PORTABLE)
119#include "base/base64.h"
120#include "net/ntlm/ntlm_test_data.h"
121#endif
122
Douglas Creager3cb042052018-11-06 23:08:52123#if BUILDFLAG(ENABLE_REPORTING)
124#include "net/network_error_logging/network_error_logging_service.h"
125#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14126#include "net/reporting/reporting_cache.h"
127#include "net/reporting/reporting_client.h"
128#include "net/reporting/reporting_header_parser.h"
129#include "net/reporting/reporting_service.h"
130#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52131#endif // BUILDFLAG(ENABLE_REPORTING)
132
robpercival214763f2016-07-01 23:27:01133using net::test::IsError;
134using net::test::IsOk;
135
[email protected]ad65a3e2013-12-25 18:18:01136using base::ASCIIToUTF16;
137
David Benjamin3b94b0f2019-04-25 23:07:52138using testing::AnyOf;
139
initial.commit586acc5fe2008-07-26 22:42:52140//-----------------------------------------------------------------------------
141
ttuttle859dc7a2015-04-23 19:42:29142namespace net {
143
[email protected]13c8a092010-07-29 06:15:44144namespace {
145
[email protected]42cba2fb2013-03-29 19:58:57146const base::string16 kBar(ASCIIToUTF16("bar"));
147const base::string16 kBar2(ASCIIToUTF16("bar2"));
148const base::string16 kBar3(ASCIIToUTF16("bar3"));
149const base::string16 kBaz(ASCIIToUTF16("baz"));
150const base::string16 kFirst(ASCIIToUTF16("first"));
151const base::string16 kFoo(ASCIIToUTF16("foo"));
152const base::string16 kFoo2(ASCIIToUTF16("foo2"));
153const base::string16 kFoo3(ASCIIToUTF16("foo3"));
154const base::string16 kFou(ASCIIToUTF16("fou"));
155const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57156const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44157
bnc2df4b522016-07-08 18:17:43158const char kAlternativeServiceHttpHeader[] =
159 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
160
ttuttle859dc7a2015-04-23 19:42:29161int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40162 return session
163 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
164 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29165 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02166}
167
ttuttle859dc7a2015-04-23 19:42:29168bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40169 return session
170 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
171 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29172 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52173}
174
[email protected]f3da152d2012-06-02 01:00:57175// Takes in a Value created from a NetLogHttpResponseParameter, and returns
176// a JSONified list of headers as a single string. Uses single quotes instead
177// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27178bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57179 if (!params)
180 return false;
[email protected]ea5ef4c2013-06-13 22:50:27181 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57182 if (!params->GetList("headers", &header_list))
183 return false;
184 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34185 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28186 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57187 return true;
188}
189
[email protected]029c83b62013-01-24 05:28:20190// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
191// used.
ttuttle859dc7a2015-04-23 19:42:29192void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20193 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19194 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25195
[email protected]029c83b62013-01-24 05:28:20196 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
197 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
198
ttuttle859dc7a2015-04-23 19:42:29199 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20200 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25201
202 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25203
[email protected]3b23a222013-05-15 21:33:25204 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25205 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
206 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25207 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25208}
209
[email protected]029c83b62013-01-24 05:28:20210// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
211// used.
ttuttle859dc7a2015-04-23 19:42:29212void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25213 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20214 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19215 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20216
217 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
218 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
219
ttuttle859dc7a2015-04-23 19:42:29220 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
221 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20222 EXPECT_LE(load_timing_info.connect_timing.connect_end,
223 load_timing_info.send_start);
224
225 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20226
[email protected]3b23a222013-05-15 21:33:25227 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20228 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
229 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25230 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20231}
232
233// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
234// used.
ttuttle859dc7a2015-04-23 19:42:29235void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20236 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19237 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20238
ttuttle859dc7a2015-04-23 19:42:29239 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20240
241 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
242 EXPECT_LE(load_timing_info.proxy_resolve_start,
243 load_timing_info.proxy_resolve_end);
244 EXPECT_LE(load_timing_info.proxy_resolve_end,
245 load_timing_info.send_start);
246 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20247
[email protected]3b23a222013-05-15 21:33:25248 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20249 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
250 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25251 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20252}
253
254// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
255// used.
ttuttle859dc7a2015-04-23 19:42:29256void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20257 int connect_timing_flags) {
258 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19259 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20260
261 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
262 EXPECT_LE(load_timing_info.proxy_resolve_start,
263 load_timing_info.proxy_resolve_end);
264 EXPECT_LE(load_timing_info.proxy_resolve_end,
265 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29266 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
267 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20268 EXPECT_LE(load_timing_info.connect_timing.connect_end,
269 load_timing_info.send_start);
270
271 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20272
[email protected]3b23a222013-05-15 21:33:25273 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20274 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
275 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25276 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25277}
278
Matt Menke2436b2f2018-12-11 18:07:11279// ProxyResolver that records URLs passed to it, and that can be told what
280// result to return.
281class CapturingProxyResolver : public ProxyResolver {
282 public:
283 CapturingProxyResolver()
284 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
285 ~CapturingProxyResolver() override = default;
286
287 int GetProxyForURL(const GURL& url,
288 ProxyInfo* results,
289 CompletionOnceCallback callback,
290 std::unique_ptr<Request>* request,
291 const NetLogWithSource& net_log) override {
292 results->UseProxyServer(proxy_server_);
293 resolved_.push_back(url);
294 return OK;
295 }
296
297 // Sets whether the resolver should use direct connections, instead of a
298 // proxy.
299 void set_proxy_server(ProxyServer proxy_server) {
300 proxy_server_ = proxy_server;
301 }
302
303 const std::vector<GURL>& resolved() const { return resolved_; }
304
305 private:
306 std::vector<GURL> resolved_;
307
308 ProxyServer proxy_server_;
309
310 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
311};
312
313class CapturingProxyResolverFactory : public ProxyResolverFactory {
314 public:
315 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
316 : ProxyResolverFactory(false), resolver_(resolver) {}
317
318 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
319 std::unique_ptr<ProxyResolver>* resolver,
320 CompletionOnceCallback callback,
321 std::unique_ptr<Request>* request) override {
322 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
323 return OK;
324 }
325
326 private:
327 ProxyResolver* resolver_;
328};
329
danakj1fd259a02016-04-16 03:17:09330std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42331 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34332 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14333}
334
xunjieli96f2a402017-06-05 17:24:27335class FailingProxyResolverFactory : public ProxyResolverFactory {
336 public:
337 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
338
339 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42340 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
341 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17342 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42343 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27344 return ERR_PAC_SCRIPT_FAILED;
345 }
346};
347
David Benjamin5cb91132018-04-06 05:54:49348class TestSSLConfigService : public SSLConfigService {
349 public:
350 explicit TestSSLConfigService(const SSLConfig& config) : config_(config) {}
Ryan Sleevib8449e02018-07-15 04:31:07351 ~TestSSLConfigService() override = default;
David Benjamin5cb91132018-04-06 05:54:49352
353 void GetSSLConfig(SSLConfig* config) override { *config = config_; }
354
Nick Harper89bc7212018-07-31 19:07:57355 bool CanShareConnectionWithClientCerts(
356 const std::string& hostname) const override {
357 return false;
358 }
359
David Benjamin5cb91132018-04-06 05:54:49360 private:
David Benjamin5cb91132018-04-06 05:54:49361 SSLConfig config_;
362};
363
[email protected]448d4ca52012-03-04 04:12:23364} // namespace
365
Bence Béky98447b12018-05-08 03:14:01366class HttpNetworkTransactionTest : public PlatformTest,
367 public WithScopedTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03368 public:
bncd16676a2016-07-20 16:23:01369 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03370 // Important to restore the per-pool limit first, since the pool limit must
371 // always be greater than group limit, and the tests reduce both limits.
372 ClientSocketPoolManager::set_max_sockets_per_pool(
373 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
374 ClientSocketPoolManager::set_max_sockets_per_group(
375 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
376 }
377
[email protected]e3ceb682011-06-28 23:55:46378 protected:
[email protected]23e482282013-06-14 16:08:02379 HttpNetworkTransactionTest()
Andrew Comminos517a92c2019-01-14 17:49:56380 : WithScopedTaskEnvironment(
381 base::test::ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME,
382 base::test::ScopedTaskEnvironment::NowSource::
383 MAIN_THREAD_MOCK_TIME),
Matt Menked6fd2a52019-03-20 06:14:36384 dummy_connect_job_params_(
385 nullptr /* client_socket_factory */,
386 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40387 nullptr /* http_auth_cache */,
388 nullptr /* http_auth_handler_factory */,
389 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13390 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40391 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36392 nullptr /* proxy_delegate */,
393 nullptr /* http_user_agent_settings */,
394 SSLClientSocketContext(),
395 SSLClientSocketContext(),
396 nullptr /* socket_performance_watcher_factory */,
397 nullptr /* network_quality_estimator */,
398 nullptr /* net_log */,
399 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56400 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15401 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03402 HttpNetworkSession::NORMAL_SOCKET_POOL)),
403 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
404 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28405 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03406 }
[email protected]bb88e1d32013-05-03 23:11:07407
[email protected]e3ceb682011-06-28 23:55:46408 struct SimpleGetHelperResult {
409 int rv;
410 std::string status_line;
411 std::string response_data;
sclittlefb249892015-09-10 21:33:22412 int64_t total_received_bytes;
413 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25414 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47415 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59416 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46417 };
418
dcheng67be2b1f2014-10-27 21:47:29419 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50420 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55421 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56422 // Set an initial delay to ensure that the first call to TimeTicks::Now()
423 // before incrementing the counter does not return a null value.
424 FastForwardBy(TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54425 }
426
dcheng67be2b1f2014-10-27 21:47:29427 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50428 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55429 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09430 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55431 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09432 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50433 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55434 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09435 }
436
Andrew Comminos1f2ff1cc2018-12-14 05:22:38437 void Check100ResponseTiming(bool use_spdy);
438
[email protected]202965992011-12-07 23:04:51439 // Either |write_failure| specifies a write failure or |read_failure|
440 // specifies a read failure when using a reused socket. In either case, the
441 // failure should cause the network transaction to resend the request, and the
442 // other argument should be NULL.
443 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
444 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52445
[email protected]a34f61ee2014-03-18 20:59:49446 // Either |write_failure| specifies a write failure or |read_failure|
447 // specifies a read failure when using a reused socket. In either case, the
448 // failure should cause the network transaction to resend the request, and the
449 // other argument should be NULL.
450 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10451 const MockRead* read_failure,
452 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49453
Ryan Sleevib8d7ea02018-05-07 20:01:01454 SimpleGetHelperResult SimpleGetHelperForData(
455 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15456 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52457
[email protected]ff007e162009-05-23 09:13:15458 HttpRequestInfo request;
459 request.method = "GET";
bncce36dca22015-04-21 22:11:23460 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10461 request.traffic_annotation =
462 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52463
vishal.b62985ca92015-04-17 08:45:51464 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07465 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09466 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16467 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27468
Ryan Sleevib8d7ea02018-05-07 20:01:01469 for (auto* provider : providers) {
470 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29471 }
initial.commit586acc5fe2008-07-26 22:42:52472
[email protected]49639fa2011-12-20 23:22:41473 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52474
eroman24bc6a12015-05-06 19:55:48475 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16476 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01477 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52478
[email protected]ff007e162009-05-23 09:13:15479 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16480 out.total_received_bytes = trans.GetTotalReceivedBytes();
481 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25482
483 // Even in the failure cases that use this function, connections are always
484 // successfully established before the error.
bnc691fda62016-08-12 00:43:16485 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25486 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
487
[email protected]ff007e162009-05-23 09:13:15488 if (out.rv != OK)
489 return out;
490
bnc691fda62016-08-12 00:43:16491 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50492 // Can't use ASSERT_* inside helper functions like this, so
493 // return an error.
wezca1070932016-05-26 20:30:52494 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50495 out.rv = ERR_UNEXPECTED;
496 return out;
497 }
[email protected]ff007e162009-05-23 09:13:15498 out.status_line = response->headers->GetStatusLine();
499
Tsuyoshi Horo01faed62019-02-20 22:11:37500 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
501 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19502
ttuttled9dbc652015-09-29 20:00:59503 bool got_endpoint =
bnc691fda62016-08-12 00:43:16504 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59505 EXPECT_EQ(got_endpoint,
506 out.remote_endpoint_after_start.address().size() > 0);
507
bnc691fda62016-08-12 00:43:16508 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01509 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40510
mmenke43758e62015-05-04 21:09:46511 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40512 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39513 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00514 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
515 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39516 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00517 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
518 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15519
[email protected]f3da152d2012-06-02 01:00:57520 std::string line;
521 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
522 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
523
[email protected]79e1fd62013-06-20 06:50:04524 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:16525 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:04526 std::string value;
527 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23528 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04529 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
530 EXPECT_EQ("keep-alive", value);
531
532 std::string response_headers;
533 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23534 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04535 response_headers);
[email protected]3deb9a52010-11-11 00:24:40536
bnc691fda62016-08-12 00:43:16537 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22538 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16539 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22540
bnc691fda62016-08-12 00:43:16541 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47542 return out;
[email protected]ff007e162009-05-23 09:13:15543 }
initial.commit586acc5fe2008-07-26 22:42:52544
Ryan Sleevib8d7ea02018-05-07 20:01:01545 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22546 MockWrite data_writes[] = {
547 MockWrite("GET / HTTP/1.1\r\n"
548 "Host: www.example.org\r\n"
549 "Connection: keep-alive\r\n\r\n"),
550 };
[email protected]5a60c8b2011-10-19 20:14:29551
Ryan Sleevib8d7ea02018-05-07 20:01:01552 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22553 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01554 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22555
Ryan Sleevib8d7ea02018-05-07 20:01:01556 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22557 return out;
[email protected]b8015c42013-12-24 15:18:19558 }
559
bnc032658ba2016-09-26 18:17:15560 void AddSSLSocketData() {
561 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49562 ssl_.ssl_info.cert =
563 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
564 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15565 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
566 }
567
[email protected]ff007e162009-05-23 09:13:15568 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
569 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52570
[email protected]ff007e162009-05-23 09:13:15571 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07572
[email protected]bb88e1d32013-05-03 23:11:07573 void CheckErrorIsPassedBack(int error, IoMode mode);
574
Matt Menked6fd2a52019-03-20 06:14:36575 const CommonConnectJobParams dummy_connect_job_params_;
576
Douglas Creager134b52e2018-11-09 18:00:14577 // These clocks are defined here, even though they're only used in the
578 // Reporting tests below, since they need to be destroyed after
579 // |session_deps_|.
580 base::SimpleTestClock clock_;
581 base::SimpleTestTickClock tick_clock_;
582
[email protected]4bd46222013-05-14 19:32:23583 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07584 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15585 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03586
587 // Original socket limits. Some tests set these. Safest to always restore
588 // them once each test has been run.
589 int old_max_group_sockets_;
590 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15591};
[email protected]231d5a32008-09-13 00:45:27592
[email protected]448d4ca52012-03-04 04:12:23593namespace {
594
ryansturm49a8cb12016-06-15 16:51:09595class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27596 public:
ryansturm49a8cb12016-06-15 16:51:09597 BeforeHeadersSentHandler()
598 : observed_before_headers_sent_with_proxy_(false),
599 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27600
ryansturm49a8cb12016-06-15 16:51:09601 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
602 HttpRequestHeaders* request_headers) {
603 observed_before_headers_sent_ = true;
604 if (!proxy_info.is_http() && !proxy_info.is_https() &&
605 !proxy_info.is_quic()) {
606 return;
607 }
608 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27609 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
610 }
611
ryansturm49a8cb12016-06-15 16:51:09612 bool observed_before_headers_sent_with_proxy() const {
613 return observed_before_headers_sent_with_proxy_;
614 }
615
616 bool observed_before_headers_sent() const {
617 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27618 }
619
620 std::string observed_proxy_server_uri() const {
621 return observed_proxy_server_uri_;
622 }
623
624 private:
ryansturm49a8cb12016-06-15 16:51:09625 bool observed_before_headers_sent_with_proxy_;
626 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27627 std::string observed_proxy_server_uri_;
628
ryansturm49a8cb12016-06-15 16:51:09629 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27630};
631
[email protected]15a5ccf82008-10-23 19:57:43632// Fill |str| with a long header list that consumes >= |size| bytes.
633void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51634 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19635 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
636 const int sizeof_row = strlen(row);
637 const int num_rows = static_cast<int>(
638 ceil(static_cast<float>(size) / sizeof_row));
639 const int sizeof_data = num_rows * sizeof_row;
640 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43641 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51642
[email protected]4ddaf2502008-10-23 18:26:19643 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43644 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19645}
646
thakis84dff942015-07-28 20:47:38647#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09648uint64_t MockGetMSTime() {
649 // Tue, 23 May 2017 20:13:07 +0000
650 return 131400439870000000;
651}
652
[email protected]385a4672009-03-11 22:21:29653// Alternative functions that eliminate randomness and dependency on the local
654// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37655void MockGenerateRandom(uint8_t* output, size_t n) {
656 // This is set to 0xaa because the client challenge for testing in
657 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
658 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29659}
660
[email protected]fe2bc6a2009-03-23 16:52:20661std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37662 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29663}
thakis84dff942015-07-28 20:47:38664#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29665
Matt Menked6fd2a52019-03-20 06:14:36666class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31667 public:
Matt Menked6fd2a52019-03-20 06:14:36668 explicit CaptureGroupIdTransportSocketPool(
669 const CommonConnectJobParams* common_connect_job_params)
670 : TransportClientSocketPool(0,
671 0,
672 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36673 ProxyServer::Direct(),
674 false /* is_for_websockets */,
Matt Menked6fd2a52019-03-20 06:14:36675 common_connect_job_params,
676 nullptr /* ssl_config_service */) {}
[email protected]e60e47a2010-07-14 03:37:18677
Matt Menkef6edce752019-03-19 17:21:56678 const ClientSocketPool::GroupId& last_group_id_received() const {
679 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49680 }
681
Tarun Bansal162eabe52018-01-20 01:16:39682 bool socket_requested() const { return socket_requested_; }
683
Matt Menke28ac03e2019-02-25 22:25:50684 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56685 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03686 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28687 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50688 RequestPriority priority,
689 const SocketTag& socket_tag,
690 ClientSocketPool::RespectLimits respect_limits,
691 ClientSocketHandle* handle,
692 CompletionOnceCallback callback,
693 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
694 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56695 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39696 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31697 return ERR_IO_PENDING;
698 }
Matt Menkef6edce752019-03-19 17:21:56699 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21700 ClientSocketHandle* handle,
701 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56702 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09703 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24704 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57705 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56706 void CloseIdleSocketsInGroup(
707 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57708 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56709 size_t IdleSocketCountInGroup(
710 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31711 return 0;
712 }
Matt Menkef6edce752019-03-19 17:21:56713 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57714 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31715 return LOAD_STATE_IDLE;
716 }
[email protected]d80a4322009-08-14 07:07:49717
718 private:
Matt Menkef6edce752019-03-19 17:21:56719 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39720 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31721};
722
[email protected]231d5a32008-09-13 00:45:27723//-----------------------------------------------------------------------------
724
[email protected]79cb5c12011-09-12 13:12:04725// Helper functions for validating that AuthChallengeInfo's are correctly
726// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58727bool CheckBasicServerAuth(
728 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04729 if (!auth_challenge)
730 return false;
731 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43732 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04733 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19734 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04735 return true;
736}
737
David Benjamin2eb827f2019-04-29 18:31:04738bool CheckBasicSecureServerAuth(
739 const base::Optional<AuthChallengeInfo>& auth_challenge) {
740 if (!auth_challenge)
741 return false;
742 EXPECT_FALSE(auth_challenge->is_proxy);
743 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
744 EXPECT_EQ("MyRealm1", auth_challenge->realm);
745 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
746 return true;
747}
748
Emily Starkf2c9bbd2019-04-09 17:08:58749bool CheckBasicProxyAuth(
750 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04751 if (!auth_challenge)
752 return false;
753 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43754 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
755 EXPECT_EQ("MyRealm1", auth_challenge->realm);
756 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
757 return true;
758}
759
Emily Starkf2c9bbd2019-04-09 17:08:58760bool CheckBasicSecureProxyAuth(
761 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43762 if (!auth_challenge)
763 return false;
764 EXPECT_TRUE(auth_challenge->is_proxy);
765 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04766 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19767 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04768 return true;
769}
770
Emily Starkf2c9bbd2019-04-09 17:08:58771bool CheckDigestServerAuth(
772 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04773 if (!auth_challenge)
774 return false;
775 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43776 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04777 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19778 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04779 return true;
780}
781
thakis84dff942015-07-28 20:47:38782#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58783bool CheckNTLMServerAuth(
784 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04785 if (!auth_challenge)
786 return false;
787 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55788 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04789 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19790 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04791 return true;
792}
David Benjamin5cb91132018-04-06 05:54:49793
Emily Starkf2c9bbd2019-04-09 17:08:58794bool CheckNTLMProxyAuth(
795 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49796 if (!auth_challenge)
797 return false;
798 EXPECT_TRUE(auth_challenge->is_proxy);
799 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
800 EXPECT_EQ(std::string(), auth_challenge->realm);
801 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
802 return true;
803}
thakis84dff942015-07-28 20:47:38804#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04805
[email protected]448d4ca52012-03-04 04:12:23806} // namespace
807
bncd16676a2016-07-20 16:23:01808TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09809 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16810 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27811}
812
bncd16676a2016-07-20 16:23:01813TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27814 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35815 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
816 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06817 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27818 };
Ryan Sleevib8d7ea02018-05-07 20:01:01819 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01820 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27821 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
822 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01823 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22824 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47825 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59826
827 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27828}
829
830// Response with no status line.
bncd16676a2016-07-20 16:23:01831TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27832 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35833 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06834 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27835 };
Ryan Sleevib8d7ea02018-05-07 20:01:01836 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41837 EXPECT_THAT(out.rv, IsOk());
838 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
839 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01840 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41841 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27842}
843
mmenkea7da6da2016-09-01 21:56:52844// Response with no status line, and a weird port. Should fail by default.
845TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
846 MockRead data_reads[] = {
847 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
848 };
849
Ryan Sleevib8d7ea02018-05-07 20:01:01850 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52851 session_deps_.socket_factory->AddSocketDataProvider(&data);
852
853 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
854
krasinc06a72a2016-12-21 03:42:46855 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58856 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19857 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52858
mmenkea7da6da2016-09-01 21:56:52859 request.method = "GET";
860 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10861 request.traffic_annotation =
862 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
863
mmenkea7da6da2016-09-01 21:56:52864 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20865 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52866 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
867}
868
Shivani Sharmafdcaefd2017-11-02 00:12:26869// Tests that request info can be destroyed after the headers phase is complete.
870TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
871 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
872 auto trans =
873 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
874
875 MockRead data_reads[] = {
876 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
877 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
878 };
Ryan Sleevib8d7ea02018-05-07 20:01:01879 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26880 session_deps_.socket_factory->AddSocketDataProvider(&data);
881
882 TestCompletionCallback callback;
883
884 {
885 auto request = std::make_unique<HttpRequestInfo>();
886 request->method = "GET";
887 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10888 request->traffic_annotation =
889 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26890
891 int rv =
892 trans->Start(request.get(), callback.callback(), NetLogWithSource());
893
894 EXPECT_THAT(callback.GetResult(rv), IsOk());
895 } // Let request info be destroyed.
896
897 trans.reset();
898}
899
mmenkea7da6da2016-09-01 21:56:52900// Response with no status line, and a weird port. Option to allow weird ports
901// enabled.
902TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPortAllowed) {
903 MockRead data_reads[] = {
904 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
905 };
906
Ryan Sleevib8d7ea02018-05-07 20:01:01907 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52908 session_deps_.socket_factory->AddSocketDataProvider(&data);
909 session_deps_.http_09_on_non_default_ports_enabled = true;
910 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
911
krasinc06a72a2016-12-21 03:42:46912 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58913 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19914 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52915
mmenkea7da6da2016-09-01 21:56:52916 request.method = "GET";
917 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10918 request.traffic_annotation =
919 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
920
mmenkea7da6da2016-09-01 21:56:52921 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20922 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52923 EXPECT_THAT(callback.GetResult(rv), IsOk());
924
925 const HttpResponseInfo* info = trans->GetResponseInfo();
926 ASSERT_TRUE(info->headers);
927 EXPECT_EQ("HTTP/0.9 200 OK", info->headers->GetStatusLine());
928
929 // Don't bother to read the body - that's verified elsewhere, important thing
930 // is that the option to allow HTTP/0.9 on non-default ports is respected.
931}
932
[email protected]231d5a32008-09-13 00:45:27933// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01934TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27935 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35936 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06937 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27938 };
Ryan Sleevib8d7ea02018-05-07 20:01:01939 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01940 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27941 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
942 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01943 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22944 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27945}
946
947// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01948TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27949 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35950 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06951 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27952 };
Ryan Sleevib8d7ea02018-05-07 20:01:01953 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01954 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27955 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
956 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01957 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22958 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27959}
960
961// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01962TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27963 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35964 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06965 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27966 };
Ryan Sleevib8d7ea02018-05-07 20:01:01967 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41968 EXPECT_THAT(out.rv, IsOk());
969 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
970 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01971 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41972 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27973}
974
975// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01976TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27977 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35978 MockRead("\n"),
979 MockRead("\n"),
980 MockRead("Q"),
981 MockRead("J"),
982 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06983 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27984 };
Ryan Sleevib8d7ea02018-05-07 20:01:01985 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01986 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27987 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
988 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01989 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22990 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27991}
992
993// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01994TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27995 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35996 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06997 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27998 };
Ryan Sleevib8d7ea02018-05-07 20:01:01999 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411000 EXPECT_THAT(out.rv, IsOk());
1001 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1002 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011003 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411004 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:521005}
1006
[email protected]f9d44aa2008-09-23 23:57:171007// Simulate a 204 response, lacking a Content-Length header, sent over a
1008// persistent connection. The response should still terminate since a 204
1009// cannot have a response body.
bncd16676a2016-07-20 16:23:011010TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:191011 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:171012 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351013 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:191014 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:061015 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:171016 };
Ryan Sleevib8d7ea02018-05-07 20:01:011017 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011018 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:171019 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
1020 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011021 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221022 int64_t response_size = reads_size - strlen(junk);
1023 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:171024}
1025
[email protected]0877e3d2009-10-17 22:29:571026// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:011027TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:191028 std::string final_chunk = "0\r\n\r\n";
1029 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1030 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:571031 MockRead data_reads[] = {
1032 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1033 MockRead("5\r\nHello\r\n"),
1034 MockRead("1\r\n"),
1035 MockRead(" \r\n"),
1036 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:191037 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:061038 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:571039 };
Ryan Sleevib8d7ea02018-05-07 20:01:011040 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011041 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:571042 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1043 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011044 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221045 int64_t response_size = reads_size - extra_data.size();
1046 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:571047}
1048
[email protected]9fe44f52010-09-23 18:36:001049// Next tests deal with http://crbug.com/56344.
1050
bncd16676a2016-07-20 16:23:011051TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001052 MultipleContentLengthHeadersNoTransferEncoding) {
1053 MockRead data_reads[] = {
1054 MockRead("HTTP/1.1 200 OK\r\n"),
1055 MockRead("Content-Length: 10\r\n"),
1056 MockRead("Content-Length: 5\r\n\r\n"),
1057 };
Ryan Sleevib8d7ea02018-05-07 20:01:011058 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011059 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001060}
1061
bncd16676a2016-07-20 16:23:011062TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041063 DuplicateContentLengthHeadersNoTransferEncoding) {
1064 MockRead data_reads[] = {
1065 MockRead("HTTP/1.1 200 OK\r\n"),
1066 MockRead("Content-Length: 5\r\n"),
1067 MockRead("Content-Length: 5\r\n\r\n"),
1068 MockRead("Hello"),
1069 };
Ryan Sleevib8d7ea02018-05-07 20:01:011070 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011071 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041072 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1073 EXPECT_EQ("Hello", out.response_data);
1074}
1075
bncd16676a2016-07-20 16:23:011076TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041077 ComplexContentLengthHeadersNoTransferEncoding) {
1078 // More than 2 dupes.
1079 {
1080 MockRead data_reads[] = {
1081 MockRead("HTTP/1.1 200 OK\r\n"),
1082 MockRead("Content-Length: 5\r\n"),
1083 MockRead("Content-Length: 5\r\n"),
1084 MockRead("Content-Length: 5\r\n\r\n"),
1085 MockRead("Hello"),
1086 };
Ryan Sleevib8d7ea02018-05-07 20:01:011087 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011088 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041089 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1090 EXPECT_EQ("Hello", out.response_data);
1091 }
1092 // HTTP/1.0
1093 {
1094 MockRead data_reads[] = {
1095 MockRead("HTTP/1.0 200 OK\r\n"),
1096 MockRead("Content-Length: 5\r\n"),
1097 MockRead("Content-Length: 5\r\n"),
1098 MockRead("Content-Length: 5\r\n\r\n"),
1099 MockRead("Hello"),
1100 };
Ryan Sleevib8d7ea02018-05-07 20:01:011101 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011102 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041103 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1104 EXPECT_EQ("Hello", out.response_data);
1105 }
1106 // 2 dupes and one mismatched.
1107 {
1108 MockRead data_reads[] = {
1109 MockRead("HTTP/1.1 200 OK\r\n"),
1110 MockRead("Content-Length: 10\r\n"),
1111 MockRead("Content-Length: 10\r\n"),
1112 MockRead("Content-Length: 5\r\n\r\n"),
1113 };
Ryan Sleevib8d7ea02018-05-07 20:01:011114 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011115 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041116 }
1117}
1118
bncd16676a2016-07-20 16:23:011119TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001120 MultipleContentLengthHeadersTransferEncoding) {
1121 MockRead data_reads[] = {
1122 MockRead("HTTP/1.1 200 OK\r\n"),
1123 MockRead("Content-Length: 666\r\n"),
1124 MockRead("Content-Length: 1337\r\n"),
1125 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1126 MockRead("5\r\nHello\r\n"),
1127 MockRead("1\r\n"),
1128 MockRead(" \r\n"),
1129 MockRead("5\r\nworld\r\n"),
1130 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061131 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001132 };
Ryan Sleevib8d7ea02018-05-07 20:01:011133 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011134 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001135 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1136 EXPECT_EQ("Hello world", out.response_data);
1137}
1138
[email protected]1628fe92011-10-04 23:04:551139// Next tests deal with http://crbug.com/98895.
1140
1141// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011142TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551143 MockRead data_reads[] = {
1144 MockRead("HTTP/1.1 200 OK\r\n"),
1145 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1146 MockRead("Content-Length: 5\r\n\r\n"),
1147 MockRead("Hello"),
1148 };
Ryan Sleevib8d7ea02018-05-07 20:01:011149 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011150 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551151 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1152 EXPECT_EQ("Hello", out.response_data);
1153}
1154
[email protected]54a9c6e52012-03-21 20:10:591155// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011156TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551157 MockRead data_reads[] = {
1158 MockRead("HTTP/1.1 200 OK\r\n"),
1159 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1160 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1161 MockRead("Content-Length: 5\r\n\r\n"),
1162 MockRead("Hello"),
1163 };
Ryan Sleevib8d7ea02018-05-07 20:01:011164 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011165 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591166 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1167 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551168}
1169
1170// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011171TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551172 MockRead data_reads[] = {
1173 MockRead("HTTP/1.1 200 OK\r\n"),
1174 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1175 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1176 MockRead("Content-Length: 5\r\n\r\n"),
1177 MockRead("Hello"),
1178 };
Ryan Sleevib8d7ea02018-05-07 20:01:011179 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011180 EXPECT_THAT(out.rv,
1181 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551182}
1183
[email protected]54a9c6e52012-03-21 20:10:591184// Checks that two identical Location headers result in no error.
1185// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011186TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551187 MockRead data_reads[] = {
1188 MockRead("HTTP/1.1 302 Redirect\r\n"),
1189 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591190 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551191 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061192 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551193 };
1194
1195 HttpRequestInfo request;
1196 request.method = "GET";
1197 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101198 request.traffic_annotation =
1199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551200
danakj1fd259a02016-04-16 03:17:091201 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551203
Ryan Sleevib8d7ea02018-05-07 20:01:011204 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071205 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551206
[email protected]49639fa2011-12-20 23:22:411207 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551208
tfarina42834112016-09-22 13:38:201209 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011210 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551211
robpercival214763f2016-07-01 23:27:011212 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551213
bnc691fda62016-08-12 00:43:161214 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521215 ASSERT_TRUE(response);
1216 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551217 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1218 std::string url;
1219 EXPECT_TRUE(response->headers->IsRedirect(&url));
1220 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471221 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551222}
1223
[email protected]1628fe92011-10-04 23:04:551224// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011225TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551226 MockRead data_reads[] = {
1227 MockRead("HTTP/1.1 302 Redirect\r\n"),
1228 MockRead("Location: http://good.com/\r\n"),
1229 MockRead("Location: http://evil.com/\r\n"),
1230 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061231 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551232 };
Ryan Sleevib8d7ea02018-05-07 20:01:011233 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011234 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551235}
1236
[email protected]ef0faf2e72009-03-05 23:27:231237// Do a request using the HEAD method. Verify that we don't try to read the
1238// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011239TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421240 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231241 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231242 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101243 request.traffic_annotation =
1244 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231245
danakj1fd259a02016-04-16 03:17:091246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161247 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091248 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161249 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091250 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1251 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271252
[email protected]ef0faf2e72009-03-05 23:27:231253 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131254 MockWrite("HEAD / HTTP/1.1\r\n"
1255 "Host: www.example.org\r\n"
1256 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231257 };
1258 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231259 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1260 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231261
mmenked39192ee2015-12-09 00:57:231262 // No response body because the test stops reading here.
1263 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231264 };
1265
Ryan Sleevib8d7ea02018-05-07 20:01:011266 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071267 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231268
[email protected]49639fa2011-12-20 23:22:411269 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231270
tfarina42834112016-09-22 13:38:201271 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011272 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231273
1274 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011275 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231276
bnc691fda62016-08-12 00:43:161277 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521278 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231279
1280 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521281 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231282 EXPECT_EQ(1234, response->headers->GetContentLength());
1283 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471284 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091285 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1286 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231287
1288 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101289 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231290 bool has_server_header = response->headers->EnumerateHeader(
1291 &iter, "Server", &server_header);
1292 EXPECT_TRUE(has_server_header);
1293 EXPECT_EQ("Blah", server_header);
1294
1295 // Reading should give EOF right away, since there is no message body
1296 // (despite non-zero content-length).
1297 std::string response_data;
bnc691fda62016-08-12 00:43:161298 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011299 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231300 EXPECT_EQ("", response_data);
1301}
1302
bncd16676a2016-07-20 16:23:011303TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521305
1306 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351307 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1308 MockRead("hello"),
1309 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1310 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061311 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521312 };
Ryan Sleevib8d7ea02018-05-07 20:01:011313 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071314 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521315
[email protected]0b0bf032010-09-21 18:08:501316 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521317 "hello", "world"
1318 };
1319
1320 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421321 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521322 request.method = "GET";
bncce36dca22015-04-21 22:11:231323 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101324 request.traffic_annotation =
1325 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521326
bnc691fda62016-08-12 00:43:161327 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271328
[email protected]49639fa2011-12-20 23:22:411329 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521330
tfarina42834112016-09-22 13:38:201331 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011332 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521333
1334 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011335 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521336
bnc691fda62016-08-12 00:43:161337 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521338 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521339
wezca1070932016-05-26 20:30:521340 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251341 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471342 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521343
1344 std::string response_data;
bnc691fda62016-08-12 00:43:161345 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011346 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251347 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521348 }
1349}
1350
bncd16676a2016-07-20 16:23:011351TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091352 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221353 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191354 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221355 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271356
[email protected]1c773ea12009-04-28 19:58:421357 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521358 request.method = "POST";
1359 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271360 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101361 request.traffic_annotation =
1362 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521363
shivanishab9a143952016-09-19 17:23:411364 // Check the upload progress returned before initialization is correct.
1365 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1366 EXPECT_EQ(0u, progress.size());
1367 EXPECT_EQ(0u, progress.position());
1368
danakj1fd259a02016-04-16 03:17:091369 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161370 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271371
initial.commit586acc5fe2008-07-26 22:42:521372 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351373 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1374 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1375 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061376 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521377 };
Ryan Sleevib8d7ea02018-05-07 20:01:011378 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071379 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521380
[email protected]49639fa2011-12-20 23:22:411381 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521382
tfarina42834112016-09-22 13:38:201383 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011384 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521385
1386 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011387 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521388
bnc691fda62016-08-12 00:43:161389 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521390 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521391
wezca1070932016-05-26 20:30:521392 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251393 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521394
1395 std::string response_data;
bnc691fda62016-08-12 00:43:161396 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011397 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251398 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521399}
1400
[email protected]3a2d3662009-03-27 03:49:141401// This test is almost the same as Ignores100 above, but the response contains
1402// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571403// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011404TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421405 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141406 request.method = "GET";
1407 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101408 request.traffic_annotation =
1409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141410
danakj1fd259a02016-04-16 03:17:091411 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161412 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271413
[email protected]3a2d3662009-03-27 03:49:141414 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571415 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1416 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141417 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061418 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141419 };
Ryan Sleevib8d7ea02018-05-07 20:01:011420 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071421 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141422
[email protected]49639fa2011-12-20 23:22:411423 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141424
tfarina42834112016-09-22 13:38:201425 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011426 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141427
1428 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011429 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141430
bnc691fda62016-08-12 00:43:161431 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521432 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141433
wezca1070932016-05-26 20:30:521434 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141435 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1436
1437 std::string response_data;
bnc691fda62016-08-12 00:43:161438 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011439 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141440 EXPECT_EQ("hello world", response_data);
1441}
1442
Andrew Comminos517a92c2019-01-14 17:49:561443TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1444 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381445 base::TimeDelta::FromMilliseconds(10);
1446
1447 HttpRequestInfo request;
1448 request.method = "GET";
1449 request.url = GURL("http://www.foo.com/");
1450 request.traffic_annotation =
1451 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1452
1453 std::vector<MockWrite> data_writes = {
1454 MockWrite(ASYNC, 0,
1455 "GET / HTTP/1.1\r\n"
1456 "Host: www.foo.com\r\n"
1457 "Connection: keep-alive\r\n\r\n"),
1458 };
1459
1460 std::vector<MockRead> data_reads = {
1461 // Write one byte of the status line, followed by a pause.
1462 MockRead(ASYNC, 1, "H"),
1463 MockRead(ASYNC, ERR_IO_PENDING, 2),
1464 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1465 MockRead(ASYNC, 4, "hello world"),
1466 MockRead(SYNCHRONOUS, OK, 5),
1467 };
1468
1469 SequencedSocketData data(data_reads, data_writes);
1470 session_deps_.socket_factory->AddSocketDataProvider(&data);
1471
1472 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1473
1474 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1475
1476 TestCompletionCallback callback;
1477
1478 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1479 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1480
1481 data.RunUntilPaused();
1482 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561483 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381484 data.Resume();
1485
1486 rv = callback.WaitForResult();
1487 EXPECT_THAT(rv, IsOk());
1488
1489 const HttpResponseInfo* response = trans.GetResponseInfo();
1490 ASSERT_TRUE(response);
1491
1492 EXPECT_TRUE(response->headers);
1493 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1494
1495 LoadTimingInfo load_timing_info;
1496 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1497 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1498 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561499 // Ensure we didn't include the delay in the TTFB time.
1500 EXPECT_EQ(load_timing_info.receive_headers_start,
1501 load_timing_info.connect_timing.connect_end);
1502 // Ensure that the mock clock advanced at all.
1503 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1504 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381505
1506 std::string response_data;
1507 rv = ReadTransaction(&trans, &response_data);
1508 EXPECT_THAT(rv, IsOk());
1509 EXPECT_EQ("hello world", response_data);
1510}
1511
1512// Tests that the time-to-first-byte reported in a transaction's load timing
1513// info uses the first response, even if 1XX/informational.
1514void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561515 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381516 base::TimeDelta::FromMilliseconds(10);
1517
1518 HttpRequestInfo request;
1519 request.method = "GET";
1520 request.url = GURL("https://www.foo.com/");
1521 request.traffic_annotation =
1522 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1523
1524 SSLSocketDataProvider ssl(ASYNC, OK);
1525 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1526
1527 std::vector<MockWrite> data_writes;
1528 std::vector<MockRead> data_reads;
1529
1530 spdy::SpdySerializedFrame spdy_req(
1531 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1532
1533 spdy::SpdyHeaderBlock spdy_resp1_headers;
1534 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1535 spdy::SpdySerializedFrame spdy_resp1(
1536 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1537 spdy::SpdySerializedFrame spdy_resp2(
1538 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1539 spdy::SpdySerializedFrame spdy_data(
1540 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1541
1542 if (use_spdy) {
1543 ssl.next_proto = kProtoHTTP2;
1544
1545 data_writes = {CreateMockWrite(spdy_req, 0)};
1546
1547 data_reads = {
1548 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1549 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1550 MockRead(SYNCHRONOUS, OK, 5),
1551 };
1552 } else {
1553 data_writes = {
1554 MockWrite(ASYNC, 0,
1555 "GET / HTTP/1.1\r\n"
1556 "Host: www.foo.com\r\n"
1557 "Connection: keep-alive\r\n\r\n"),
1558 };
1559
1560 data_reads = {
1561 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1562 MockRead(ASYNC, ERR_IO_PENDING, 2),
1563
1564 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1565 MockRead(ASYNC, 4, "hello world"),
1566 MockRead(SYNCHRONOUS, OK, 5),
1567 };
1568 }
1569
1570 SequencedSocketData data(data_reads, data_writes);
1571 session_deps_.socket_factory->AddSocketDataProvider(&data);
1572
1573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1574
1575 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1576
1577 TestCompletionCallback callback;
1578
1579 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1580 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1581
1582 data.RunUntilPaused();
1583 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1584 // the delay before parsing the 200 response.
1585 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561586 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381587 data.Resume();
1588
1589 rv = callback.WaitForResult();
1590 EXPECT_THAT(rv, IsOk());
1591
1592 const HttpResponseInfo* response = trans.GetResponseInfo();
1593 ASSERT_TRUE(response);
1594
1595 LoadTimingInfo load_timing_info;
1596 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1597 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1598 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561599 // Ensure we didn't include the delay in the TTFB time.
1600 EXPECT_EQ(load_timing_info.receive_headers_start,
1601 load_timing_info.connect_timing.connect_end);
1602 // Ensure that the mock clock advanced at all.
1603 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1604 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381605
1606 std::string response_data;
1607 rv = ReadTransaction(&trans, &response_data);
1608 EXPECT_THAT(rv, IsOk());
1609 EXPECT_EQ("hello world", response_data);
1610}
1611
Andrew Comminos517a92c2019-01-14 17:49:561612TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381613 Check100ResponseTiming(false /* use_spdy */);
1614}
1615
Andrew Comminos517a92c2019-01-14 17:49:561616TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381617 Check100ResponseTiming(true /* use_spdy */);
1618}
1619
bncd16676a2016-07-20 16:23:011620TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081621 HttpRequestInfo request;
1622 request.method = "POST";
1623 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101624 request.traffic_annotation =
1625 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081626
danakj1fd259a02016-04-16 03:17:091627 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161628 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081629
1630 MockRead data_reads[] = {
1631 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1632 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381633 };
Ryan Sleevib8d7ea02018-05-07 20:01:011634 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081635 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381636
zmo9528c9f42015-08-04 22:12:081637 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381638
tfarina42834112016-09-22 13:38:201639 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011640 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381641
zmo9528c9f42015-08-04 22:12:081642 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011643 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381644
zmo9528c9f42015-08-04 22:12:081645 std::string response_data;
bnc691fda62016-08-12 00:43:161646 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011647 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081648 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381649}
1650
bncd16676a2016-07-20 16:23:011651TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381652 HttpRequestInfo request;
1653 request.method = "POST";
1654 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101655 request.traffic_annotation =
1656 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381657
danakj1fd259a02016-04-16 03:17:091658 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161659 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271660
[email protected]ee9410e72010-01-07 01:42:381661 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061662 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381663 };
Ryan Sleevib8d7ea02018-05-07 20:01:011664 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071665 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381666
[email protected]49639fa2011-12-20 23:22:411667 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381668
tfarina42834112016-09-22 13:38:201669 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011670 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381671
1672 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011673 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381674}
1675
[email protected]23e482282013-06-14 16:08:021676void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511677 const MockWrite* write_failure,
1678 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421679 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521680 request.method = "GET";
1681 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101682 request.traffic_annotation =
1683 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521684
vishal.b62985ca92015-04-17 08:45:511685 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071686 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091687 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271688
[email protected]202965992011-12-07 23:04:511689 // Written data for successfully sending both requests.
1690 MockWrite data1_writes[] = {
1691 MockWrite("GET / HTTP/1.1\r\n"
1692 "Host: www.foo.com\r\n"
1693 "Connection: keep-alive\r\n\r\n"),
1694 MockWrite("GET / HTTP/1.1\r\n"
1695 "Host: www.foo.com\r\n"
1696 "Connection: keep-alive\r\n\r\n")
1697 };
1698
1699 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521700 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351701 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1702 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061703 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521704 };
[email protected]202965992011-12-07 23:04:511705
1706 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491707 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511708 data1_writes[1] = *write_failure;
1709 } else {
1710 ASSERT_TRUE(read_failure);
1711 data1_reads[2] = *read_failure;
1712 }
1713
Ryan Sleevib8d7ea02018-05-07 20:01:011714 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071715 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521716
1717 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351718 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1719 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061720 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521721 };
Ryan Sleevib8d7ea02018-05-07 20:01:011722 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071723 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521724
thestig9d3bb0c2015-01-24 00:49:511725 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521726 "hello", "world"
1727 };
1728
mikecironef22f9812016-10-04 03:40:191729 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521730 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411731 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521732
bnc691fda62016-08-12 00:43:161733 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521734
tfarina42834112016-09-22 13:38:201735 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011736 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521737
1738 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011739 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521740
[email protected]58e32bb2013-01-21 18:23:251741 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161742 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251743 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1744 if (i == 0) {
1745 first_socket_log_id = load_timing_info.socket_log_id;
1746 } else {
1747 // The second request should be using a new socket.
1748 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1749 }
1750
bnc691fda62016-08-12 00:43:161751 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521752 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521753
wezca1070932016-05-26 20:30:521754 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471755 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251756 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521757
1758 std::string response_data;
bnc691fda62016-08-12 00:43:161759 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011760 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251761 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521762 }
1763}
[email protected]3d2a59b2008-09-26 19:44:251764
[email protected]a34f61ee2014-03-18 20:59:491765void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1766 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101767 const MockRead* read_failure,
1768 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491769 HttpRequestInfo request;
1770 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101771 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101772 request.traffic_annotation =
1773 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491774
vishal.b62985ca92015-04-17 08:45:511775 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491776 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091777 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491778
[email protected]09356c652014-03-25 15:36:101779 SSLSocketDataProvider ssl1(ASYNC, OK);
1780 SSLSocketDataProvider ssl2(ASYNC, OK);
1781 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361782 ssl1.next_proto = kProtoHTTP2;
1783 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101784 }
1785 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491787
[email protected]09356c652014-03-25 15:36:101788 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131789 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491790 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131791 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351792 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131793 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191794 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491795
[email protected]09356c652014-03-25 15:36:101796 // HTTP/1.1 versions of the request and response.
1797 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1798 "Host: www.foo.com\r\n"
1799 "Connection: keep-alive\r\n\r\n";
1800 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1801 const char kHttpData[] = "hello";
1802
1803 std::vector<MockRead> data1_reads;
1804 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491805 if (write_failure) {
1806 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101807 data1_writes.push_back(*write_failure);
1808 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491809 } else {
1810 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101811 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411812 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101813 } else {
1814 data1_writes.push_back(MockWrite(kHttpRequest));
1815 }
1816 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491817 }
1818
Ryan Sleevib8d7ea02018-05-07 20:01:011819 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491820 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1821
[email protected]09356c652014-03-25 15:36:101822 std::vector<MockRead> data2_reads;
1823 std::vector<MockWrite> data2_writes;
1824
1825 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411826 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101827
bncdf80d44fd2016-07-15 20:27:411828 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1829 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101830 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1831 } else {
1832 data2_writes.push_back(
1833 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1834
1835 data2_reads.push_back(
1836 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1837 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1838 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1839 }
Ryan Sleevib8d7ea02018-05-07 20:01:011840 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491841 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1842
1843 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591844 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491845 // Wait for the preconnect to complete.
1846 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1847 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231848 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491849
1850 // Make the request.
1851 TestCompletionCallback callback;
1852
bnc691fda62016-08-12 00:43:161853 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491854
tfarina42834112016-09-22 13:38:201855 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011856 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491857
1858 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011859 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491860
1861 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161862 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101863 TestLoadTimingNotReused(
1864 load_timing_info,
1865 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491866
bnc691fda62016-08-12 00:43:161867 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521868 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491869
wezca1070932016-05-26 20:30:521870 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021871 if (response->was_fetched_via_spdy) {
1872 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1873 } else {
1874 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1875 }
[email protected]a34f61ee2014-03-18 20:59:491876
1877 std::string response_data;
bnc691fda62016-08-12 00:43:161878 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011879 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101880 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491881}
1882
Biljith Jayan45a41722017-08-16 18:43:141883// Test that we do not retry indefinitely when a server sends an error like
1884// ERR_SPDY_PING_FAILED, ERR_SPDY_SERVER_REFUSED_STREAM,
1885// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1886TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1887 HttpRequestInfo request;
1888 request.method = "GET";
1889 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101890 request.traffic_annotation =
1891 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141892
1893 // Check whether we give up after the third try.
1894
1895 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131896 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141897 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131898 spdy::SpdySerializedFrame spdy_response_go_away(
1899 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011900 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1901 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141902
1903 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011904 StaticSocketDataProvider data1(data_read1, data_write);
1905 StaticSocketDataProvider data2(data_read1, data_write);
1906 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141907
1908 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1909 AddSSLSocketData();
1910 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1911 AddSSLSocketData();
1912 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1913 AddSSLSocketData();
1914
1915 TestCompletionCallback callback;
1916 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1917 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1918
1919 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1920 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1921
1922 rv = callback.WaitForResult();
1923 EXPECT_THAT(rv, IsError(ERR_SPDY_SERVER_REFUSED_STREAM));
1924}
1925
1926TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1927 HttpRequestInfo request;
1928 request.method = "GET";
1929 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101930 request.traffic_annotation =
1931 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141932
1933 // Check whether we try atleast thrice before giving up.
1934
1935 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131936 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141937 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131938 spdy::SpdySerializedFrame spdy_response_go_away(
1939 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011940 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1941 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141942
1943 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131944 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141945 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131946 spdy::SpdySerializedFrame spdy_data(
1947 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141948 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1949 CreateMockRead(spdy_data, 2)};
1950
1951 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011952 StaticSocketDataProvider data1(data_read1, data_write);
1953 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141954 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011955 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141956
1957 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1958 AddSSLSocketData();
1959 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1960 AddSSLSocketData();
1961 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1962 AddSSLSocketData();
1963
1964 TestCompletionCallback callback;
1965 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1966 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1967
1968 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1969 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1970
1971 rv = callback.WaitForResult();
1972 EXPECT_THAT(rv, IsOk());
1973}
1974
bncd16676a2016-07-20 16:23:011975TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061976 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351977 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511978}
1979
bncd16676a2016-07-20 16:23:011980TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061981 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351982 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251983}
1984
bncd16676a2016-07-20 16:23:011985TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061986 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351987 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251988}
1989
[email protected]d58ceea82014-06-04 10:55:541990// Make sure that on a 408 response (Request Timeout), the request is retried,
1991// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011992TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541993 MockRead read_failure(SYNCHRONOUS,
1994 "HTTP/1.1 408 Request Timeout\r\n"
1995 "Connection: Keep-Alive\r\n"
1996 "Content-Length: 6\r\n\r\n"
1997 "Pickle");
Raul Tambre94493c652019-03-11 17:18:351998 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:541999}
2000
bncd16676a2016-07-20 16:23:012001TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:492002 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352003 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:492004}
2005
bncd16676a2016-07-20 16:23:012006TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:492007 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352008 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:492009}
2010
bncd16676a2016-07-20 16:23:012011TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:492012 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352013 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:102014}
2015
bncd16676a2016-07-20 16:23:012016TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102017 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352018 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:102019}
2020
[email protected]d58ceea82014-06-04 10:55:542021// Make sure that on a 408 response (Request Timeout), the request is retried,
2022// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:012023TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:542024 MockRead read_failure(SYNCHRONOUS,
2025 "HTTP/1.1 408 Request Timeout\r\n"
2026 "Connection: Keep-Alive\r\n"
2027 "Content-Length: 6\r\n\r\n"
2028 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352029 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2030 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:542031}
2032
bncd16676a2016-07-20 16:23:012033TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:102034 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352035 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:102036}
2037
bncd16676a2016-07-20 16:23:012038TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:102039 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352040 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102041}
2042
bncd16676a2016-07-20 16:23:012043TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:102044 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352045 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102046}
2047
bncd16676a2016-07-20 16:23:012048TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102049 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352050 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:492051}
2052
bncd16676a2016-07-20 16:23:012053TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422054 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252055 request.method = "GET";
bncce36dca22015-04-21 22:11:232056 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102057 request.traffic_annotation =
2058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252059
danakj1fd259a02016-04-16 03:17:092060 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162061 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272062
[email protected]3d2a59b2008-09-26 19:44:252063 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062064 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352065 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2066 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062067 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252068 };
Ryan Sleevib8d7ea02018-05-07 20:01:012069 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072070 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252071
[email protected]49639fa2011-12-20 23:22:412072 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252073
tfarina42834112016-09-22 13:38:202074 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012075 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252076
2077 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012078 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592079
2080 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162081 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592082 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252083}
2084
2085// What do various browsers do when the server closes a non-keepalive
2086// connection without sending any response header or body?
2087//
2088// IE7: error page
2089// Safari 3.1.2 (Windows): error page
2090// Firefox 3.0.1: blank page
2091// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422092// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2093// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012094TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252095 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062096 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352097 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2098 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062099 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252100 };
Ryan Sleevib8d7ea02018-05-07 20:01:012101 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012102 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252103}
[email protected]1826a402014-01-08 15:40:482104
[email protected]7a5378b2012-11-04 03:25:172105// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2106// tests. There was a bug causing HttpNetworkTransaction to hang in the
2107// destructor in such situations.
2108// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012109TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172110 HttpRequestInfo request;
2111 request.method = "GET";
bncce36dca22015-04-21 22:11:232112 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102113 request.traffic_annotation =
2114 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172115
danakj1fd259a02016-04-16 03:17:092116 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582117 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192118 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172119
2120 MockRead data_reads[] = {
2121 MockRead("HTTP/1.0 200 OK\r\n"),
2122 MockRead("Connection: keep-alive\r\n"),
2123 MockRead("Content-Length: 100\r\n\r\n"),
2124 MockRead("hello"),
2125 MockRead(SYNCHRONOUS, 0),
2126 };
Ryan Sleevib8d7ea02018-05-07 20:01:012127 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072128 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172129
2130 TestCompletionCallback callback;
2131
tfarina42834112016-09-22 13:38:202132 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012133 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172134
2135 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012136 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172137
Victor Costan9c7302b2018-08-27 16:39:442138 scoped_refptr<IOBufferWithSize> io_buf =
2139 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502140 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172141 if (rv == ERR_IO_PENDING)
2142 rv = callback.WaitForResult();
2143 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502144 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012145 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172146
2147 trans.reset();
fdoray92e35a72016-06-10 15:54:552148 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172149 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2150}
2151
bncd16676a2016-07-20 16:23:012152TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172153 HttpRequestInfo request;
2154 request.method = "GET";
bncce36dca22015-04-21 22:11:232155 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102156 request.traffic_annotation =
2157 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172158
danakj1fd259a02016-04-16 03:17:092159 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582160 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192161 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172162
2163 MockRead data_reads[] = {
2164 MockRead("HTTP/1.0 200 OK\r\n"),
2165 MockRead("Connection: keep-alive\r\n"),
2166 MockRead("Content-Length: 100\r\n\r\n"),
2167 MockRead(SYNCHRONOUS, 0),
2168 };
Ryan Sleevib8d7ea02018-05-07 20:01:012169 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072170 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172171
2172 TestCompletionCallback callback;
2173
tfarina42834112016-09-22 13:38:202174 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012175 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172176
2177 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012178 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172179
Victor Costan9c7302b2018-08-27 16:39:442180 scoped_refptr<IOBufferWithSize> io_buf(
2181 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502182 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172183 if (rv == ERR_IO_PENDING)
2184 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012185 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172186
2187 trans.reset();
fdoray92e35a72016-06-10 15:54:552188 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172189 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2190}
2191
[email protected]0b0bf032010-09-21 18:08:502192// Test that we correctly reuse a keep-alive connection after not explicitly
2193// reading the body.
bncd16676a2016-07-20 16:23:012194TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132195 HttpRequestInfo request;
2196 request.method = "GET";
2197 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102198 request.traffic_annotation =
2199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132200
vishal.b62985ca92015-04-17 08:45:512201 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072202 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092203 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272204
mmenkecc2298e2015-12-07 18:20:182205 const char* request_data =
2206 "GET / HTTP/1.1\r\n"
2207 "Host: www.foo.com\r\n"
2208 "Connection: keep-alive\r\n\r\n";
2209 MockWrite data_writes[] = {
2210 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2211 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2212 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2213 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2214 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2215 };
2216
[email protected]0b0bf032010-09-21 18:08:502217 // Note that because all these reads happen in the same
2218 // StaticSocketDataProvider, it shows that the same socket is being reused for
2219 // all transactions.
mmenkecc2298e2015-12-07 18:20:182220 MockRead data_reads[] = {
2221 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2222 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2223 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2224 MockRead(ASYNC, 7,
2225 "HTTP/1.1 302 Found\r\n"
2226 "Content-Length: 0\r\n\r\n"),
2227 MockRead(ASYNC, 9,
2228 "HTTP/1.1 302 Found\r\n"
2229 "Content-Length: 5\r\n\r\n"
2230 "hello"),
2231 MockRead(ASYNC, 11,
2232 "HTTP/1.1 301 Moved Permanently\r\n"
2233 "Content-Length: 0\r\n\r\n"),
2234 MockRead(ASYNC, 13,
2235 "HTTP/1.1 301 Moved Permanently\r\n"
2236 "Content-Length: 5\r\n\r\n"
2237 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132238
mmenkecc2298e2015-12-07 18:20:182239 // In the next two rounds, IsConnectedAndIdle returns false, due to
2240 // the set_busy_before_sync_reads(true) call, while the
2241 // HttpNetworkTransaction is being shut down, but the socket is still
2242 // reuseable. See http://crbug.com/544255.
2243 MockRead(ASYNC, 15,
2244 "HTTP/1.1 200 Hunky-Dory\r\n"
2245 "Content-Length: 5\r\n\r\n"),
2246 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132247
mmenkecc2298e2015-12-07 18:20:182248 MockRead(ASYNC, 18,
2249 "HTTP/1.1 200 Hunky-Dory\r\n"
2250 "Content-Length: 5\r\n\r\n"
2251 "he"),
2252 MockRead(SYNCHRONOUS, 19, "llo"),
2253
2254 // The body of the final request is actually read.
2255 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2256 MockRead(ASYNC, 22, "hello"),
2257 };
Ryan Sleevib8d7ea02018-05-07 20:01:012258 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182259 data.set_busy_before_sync_reads(true);
2260 session_deps_.socket_factory->AddSocketDataProvider(&data);
2261
Avi Drissman4365a4782018-12-28 19:26:242262 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502263 std::string response_lines[kNumUnreadBodies];
2264
mikecironef22f9812016-10-04 03:40:192265 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182266 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412267 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132268
Jeremy Roman0579ed62017-08-29 15:56:192269 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582270 session.get());
[email protected]fc31d6a42010-06-24 18:05:132271
tfarina42834112016-09-22 13:38:202272 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012273 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132274
[email protected]58e32bb2013-01-21 18:23:252275 LoadTimingInfo load_timing_info;
2276 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2277 if (i == 0) {
2278 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2279 first_socket_log_id = load_timing_info.socket_log_id;
2280 } else {
2281 TestLoadTimingReused(load_timing_info);
2282 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2283 }
2284
[email protected]fc31d6a42010-06-24 18:05:132285 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182286 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132287
mmenkecc2298e2015-12-07 18:20:182288 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502289 response_lines[i] = response->headers->GetStatusLine();
2290
mmenkecc2298e2015-12-07 18:20:182291 // Delete the transaction without reading the response bodies. Then spin
2292 // the message loop, so the response bodies are drained.
2293 trans.reset();
2294 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132295 }
[email protected]0b0bf032010-09-21 18:08:502296
2297 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182298 "HTTP/1.1 204 No Content",
2299 "HTTP/1.1 205 Reset Content",
2300 "HTTP/1.1 304 Not Modified",
2301 "HTTP/1.1 302 Found",
2302 "HTTP/1.1 302 Found",
2303 "HTTP/1.1 301 Moved Permanently",
2304 "HTTP/1.1 301 Moved Permanently",
2305 "HTTP/1.1 200 Hunky-Dory",
2306 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502307 };
2308
Avi Drissman4365a4782018-12-28 19:26:242309 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272310 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502311
2312 for (int i = 0; i < kNumUnreadBodies; ++i)
2313 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2314
[email protected]49639fa2011-12-20 23:22:412315 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162316 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202317 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012318 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162319 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182320 ASSERT_TRUE(response);
2321 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502322 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2323 std::string response_data;
bnc691fda62016-08-12 00:43:162324 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012325 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502326 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132327}
2328
mmenke5f94fda2016-06-02 20:54:132329// Sockets that receive extra data after a response is complete should not be
2330// reused.
bncd16676a2016-07-20 16:23:012331TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132332 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2333 MockWrite data_writes1[] = {
2334 MockWrite("HEAD / HTTP/1.1\r\n"
2335 "Host: www.borked.com\r\n"
2336 "Connection: keep-alive\r\n\r\n"),
2337 };
2338
2339 MockRead data_reads1[] = {
2340 MockRead("HTTP/1.1 200 OK\r\n"
2341 "Connection: keep-alive\r\n"
2342 "Content-Length: 22\r\n\r\n"
2343 "This server is borked."),
2344 };
2345
2346 MockWrite data_writes2[] = {
2347 MockWrite("GET /foo HTTP/1.1\r\n"
2348 "Host: www.borked.com\r\n"
2349 "Connection: keep-alive\r\n\r\n"),
2350 };
2351
2352 MockRead data_reads2[] = {
2353 MockRead("HTTP/1.1 200 OK\r\n"
2354 "Content-Length: 3\r\n\r\n"
2355 "foo"),
2356 };
Ryan Sleevib8d7ea02018-05-07 20:01:012357 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132358 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012359 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132360 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2361
2362 TestCompletionCallback callback;
2363 HttpRequestInfo request1;
2364 request1.method = "HEAD";
2365 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102366 request1.traffic_annotation =
2367 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132368
bnc87dcefc2017-05-25 12:47:582369 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192370 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202371 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012372 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132373
2374 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2375 ASSERT_TRUE(response1);
2376 ASSERT_TRUE(response1->headers);
2377 EXPECT_EQ(200, response1->headers->response_code());
2378 EXPECT_TRUE(response1->headers->IsKeepAlive());
2379
2380 std::string response_data1;
robpercival214763f2016-07-01 23:27:012381 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132382 EXPECT_EQ("", response_data1);
2383 // Deleting the transaction attempts to release the socket back into the
2384 // socket pool.
2385 trans1.reset();
2386
2387 HttpRequestInfo request2;
2388 request2.method = "GET";
2389 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102390 request2.traffic_annotation =
2391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132392
bnc87dcefc2017-05-25 12:47:582393 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192394 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202395 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012396 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132397
2398 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2399 ASSERT_TRUE(response2);
2400 ASSERT_TRUE(response2->headers);
2401 EXPECT_EQ(200, response2->headers->response_code());
2402
2403 std::string response_data2;
robpercival214763f2016-07-01 23:27:012404 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132405 EXPECT_EQ("foo", response_data2);
2406}
2407
bncd16676a2016-07-20 16:23:012408TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132409 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2410 MockWrite data_writes1[] = {
2411 MockWrite("GET / HTTP/1.1\r\n"
2412 "Host: www.borked.com\r\n"
2413 "Connection: keep-alive\r\n\r\n"),
2414 };
2415
2416 MockRead data_reads1[] = {
2417 MockRead("HTTP/1.1 200 OK\r\n"
2418 "Connection: keep-alive\r\n"
2419 "Content-Length: 22\r\n\r\n"
2420 "This server is borked."
2421 "Bonus data!"),
2422 };
2423
2424 MockWrite data_writes2[] = {
2425 MockWrite("GET /foo HTTP/1.1\r\n"
2426 "Host: www.borked.com\r\n"
2427 "Connection: keep-alive\r\n\r\n"),
2428 };
2429
2430 MockRead data_reads2[] = {
2431 MockRead("HTTP/1.1 200 OK\r\n"
2432 "Content-Length: 3\r\n\r\n"
2433 "foo"),
2434 };
Ryan Sleevib8d7ea02018-05-07 20:01:012435 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132436 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012437 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132438 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2439
2440 TestCompletionCallback callback;
2441 HttpRequestInfo request1;
2442 request1.method = "GET";
2443 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102444 request1.traffic_annotation =
2445 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132446
bnc87dcefc2017-05-25 12:47:582447 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192448 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202449 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012450 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132451
2452 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2453 ASSERT_TRUE(response1);
2454 ASSERT_TRUE(response1->headers);
2455 EXPECT_EQ(200, response1->headers->response_code());
2456 EXPECT_TRUE(response1->headers->IsKeepAlive());
2457
2458 std::string response_data1;
robpercival214763f2016-07-01 23:27:012459 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132460 EXPECT_EQ("This server is borked.", response_data1);
2461 // Deleting the transaction attempts to release the socket back into the
2462 // socket pool.
2463 trans1.reset();
2464
2465 HttpRequestInfo request2;
2466 request2.method = "GET";
2467 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102468 request2.traffic_annotation =
2469 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132470
bnc87dcefc2017-05-25 12:47:582471 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192472 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202473 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012474 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132475
2476 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2477 ASSERT_TRUE(response2);
2478 ASSERT_TRUE(response2->headers);
2479 EXPECT_EQ(200, response2->headers->response_code());
2480
2481 std::string response_data2;
robpercival214763f2016-07-01 23:27:012482 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132483 EXPECT_EQ("foo", response_data2);
2484}
2485
bncd16676a2016-07-20 16:23:012486TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132487 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2488 MockWrite data_writes1[] = {
2489 MockWrite("GET / HTTP/1.1\r\n"
2490 "Host: www.borked.com\r\n"
2491 "Connection: keep-alive\r\n\r\n"),
2492 };
2493
2494 MockRead data_reads1[] = {
2495 MockRead("HTTP/1.1 200 OK\r\n"
2496 "Connection: keep-alive\r\n"
2497 "Transfer-Encoding: chunked\r\n\r\n"),
2498 MockRead("16\r\nThis server is borked.\r\n"),
2499 MockRead("0\r\n\r\nBonus data!"),
2500 };
2501
2502 MockWrite data_writes2[] = {
2503 MockWrite("GET /foo HTTP/1.1\r\n"
2504 "Host: www.borked.com\r\n"
2505 "Connection: keep-alive\r\n\r\n"),
2506 };
2507
2508 MockRead data_reads2[] = {
2509 MockRead("HTTP/1.1 200 OK\r\n"
2510 "Content-Length: 3\r\n\r\n"
2511 "foo"),
2512 };
Ryan Sleevib8d7ea02018-05-07 20:01:012513 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132514 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012515 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132516 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2517
2518 TestCompletionCallback callback;
2519 HttpRequestInfo request1;
2520 request1.method = "GET";
2521 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102522 request1.traffic_annotation =
2523 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132524
bnc87dcefc2017-05-25 12:47:582525 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192526 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202527 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012528 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132529
2530 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2531 ASSERT_TRUE(response1);
2532 ASSERT_TRUE(response1->headers);
2533 EXPECT_EQ(200, response1->headers->response_code());
2534 EXPECT_TRUE(response1->headers->IsKeepAlive());
2535
2536 std::string response_data1;
robpercival214763f2016-07-01 23:27:012537 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132538 EXPECT_EQ("This server is borked.", response_data1);
2539 // Deleting the transaction attempts to release the socket back into the
2540 // socket pool.
2541 trans1.reset();
2542
2543 HttpRequestInfo request2;
2544 request2.method = "GET";
2545 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102546 request2.traffic_annotation =
2547 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132548
bnc87dcefc2017-05-25 12:47:582549 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192550 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202551 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012552 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132553
2554 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2555 ASSERT_TRUE(response2);
2556 ASSERT_TRUE(response2->headers);
2557 EXPECT_EQ(200, response2->headers->response_code());
2558
2559 std::string response_data2;
robpercival214763f2016-07-01 23:27:012560 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132561 EXPECT_EQ("foo", response_data2);
2562}
2563
2564// This is a little different from the others - it tests the case that the
2565// HttpStreamParser doesn't know if there's extra data on a socket or not when
2566// the HttpNetworkTransaction is torn down, because the response body hasn't
2567// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012568TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132569 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2570 MockWrite data_writes1[] = {
2571 MockWrite("GET / HTTP/1.1\r\n"
2572 "Host: www.borked.com\r\n"
2573 "Connection: keep-alive\r\n\r\n"),
2574 };
2575
2576 MockRead data_reads1[] = {
2577 MockRead("HTTP/1.1 200 OK\r\n"
2578 "Connection: keep-alive\r\n"
2579 "Transfer-Encoding: chunked\r\n\r\n"),
2580 MockRead("16\r\nThis server is borked.\r\n"),
2581 MockRead("0\r\n\r\nBonus data!"),
2582 };
Ryan Sleevib8d7ea02018-05-07 20:01:012583 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132584 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2585
2586 TestCompletionCallback callback;
2587 HttpRequestInfo request1;
2588 request1.method = "GET";
2589 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102590 request1.traffic_annotation =
2591 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132592
bnc87dcefc2017-05-25 12:47:582593 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192594 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582595 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012596 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132597
bnc87dcefc2017-05-25 12:47:582598 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132599 ASSERT_TRUE(response1);
2600 ASSERT_TRUE(response1->headers);
2601 EXPECT_EQ(200, response1->headers->response_code());
2602 EXPECT_TRUE(response1->headers->IsKeepAlive());
2603
2604 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2605 // response body.
bnc87dcefc2017-05-25 12:47:582606 trans.reset();
mmenke5f94fda2016-06-02 20:54:132607
2608 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2609 // socket can't be reused, rather than returning it to the socket pool.
2610 base::RunLoop().RunUntilIdle();
2611
2612 // There should be no idle sockets in the pool.
2613 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2614}
2615
[email protected]038e9a32008-10-08 22:40:162616// Test the request-challenge-retry sequence for basic auth.
2617// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012618TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422619 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162620 request.method = "GET";
bncce36dca22015-04-21 22:11:232621 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102622 request.traffic_annotation =
2623 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162624
vishal.b62985ca92015-04-17 08:45:512625 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072626 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092627 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162628 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272629
[email protected]f9ee6b52008-11-08 06:46:232630 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232631 MockWrite(
2632 "GET / HTTP/1.1\r\n"
2633 "Host: www.example.org\r\n"
2634 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232635 };
2636
[email protected]038e9a32008-10-08 22:40:162637 MockRead data_reads1[] = {
2638 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2639 // Give a couple authenticate options (only the middle one is actually
2640 // supported).
[email protected]22927ad2009-09-21 19:56:192641 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162642 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2643 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2644 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2645 // Large content-length -- won't matter, as connection will be reset.
2646 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062647 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162648 };
2649
2650 // After calling trans->RestartWithAuth(), this is the request we should
2651 // be issuing -- the final header line contains the credentials.
2652 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232653 MockWrite(
2654 "GET / HTTP/1.1\r\n"
2655 "Host: www.example.org\r\n"
2656 "Connection: keep-alive\r\n"
2657 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162658 };
2659
2660 // Lastly, the server responds with the actual content.
2661 MockRead data_reads2[] = {
2662 MockRead("HTTP/1.0 200 OK\r\n"),
2663 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2664 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062665 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162666 };
2667
Ryan Sleevib8d7ea02018-05-07 20:01:012668 StaticSocketDataProvider data1(data_reads1, data_writes1);
2669 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072670 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2671 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162672
[email protected]49639fa2011-12-20 23:22:412673 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162674
tfarina42834112016-09-22 13:38:202675 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012676 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162677
2678 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012679 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162680
[email protected]58e32bb2013-01-21 18:23:252681 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162682 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252683 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2684
Ryan Sleevib8d7ea02018-05-07 20:01:012685 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162686 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012687 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162688 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192689
bnc691fda62016-08-12 00:43:162690 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522691 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582692 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162693
[email protected]49639fa2011-12-20 23:22:412694 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162695
bnc691fda62016-08-12 00:43:162696 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012697 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162698
2699 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012700 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162701
[email protected]58e32bb2013-01-21 18:23:252702 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162703 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252704 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2705 // The load timing after restart should have a new socket ID, and times after
2706 // those of the first load timing.
2707 EXPECT_LE(load_timing_info1.receive_headers_end,
2708 load_timing_info2.connect_timing.connect_start);
2709 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2710
Ryan Sleevib8d7ea02018-05-07 20:01:012711 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162712 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012713 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162714 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192715
bnc691fda62016-08-12 00:43:162716 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522717 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582718 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162719 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162720}
2721
ttuttled9dbc652015-09-29 20:00:592722// Test the request-challenge-retry sequence for basic auth.
2723// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012724TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592725 HttpRequestInfo request;
2726 request.method = "GET";
2727 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102728 request.traffic_annotation =
2729 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592730
2731 TestNetLog log;
2732 MockHostResolver* resolver = new MockHostResolver();
2733 session_deps_.net_log = &log;
2734 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092735 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162736 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592737
2738 resolver->rules()->ClearRules();
2739 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2740
2741 MockWrite data_writes1[] = {
2742 MockWrite("GET / HTTP/1.1\r\n"
2743 "Host: www.example.org\r\n"
2744 "Connection: keep-alive\r\n\r\n"),
2745 };
2746
2747 MockRead data_reads1[] = {
2748 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2749 // Give a couple authenticate options (only the middle one is actually
2750 // supported).
2751 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2752 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2753 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2754 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2755 // Large content-length -- won't matter, as connection will be reset.
2756 MockRead("Content-Length: 10000\r\n\r\n"),
2757 MockRead(SYNCHRONOUS, ERR_FAILED),
2758 };
2759
2760 // After calling trans->RestartWithAuth(), this is the request we should
2761 // be issuing -- the final header line contains the credentials.
2762 MockWrite data_writes2[] = {
2763 MockWrite("GET / HTTP/1.1\r\n"
2764 "Host: www.example.org\r\n"
2765 "Connection: keep-alive\r\n"
2766 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2767 };
2768
2769 // Lastly, the server responds with the actual content.
2770 MockRead data_reads2[] = {
2771 MockRead("HTTP/1.0 200 OK\r\n"),
2772 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2773 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2774 };
2775
Ryan Sleevib8d7ea02018-05-07 20:01:012776 StaticSocketDataProvider data1(data_reads1, data_writes1);
2777 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592778 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2779 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2780
2781 TestCompletionCallback callback1;
2782
bnc691fda62016-08-12 00:43:162783 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202784 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592785
2786 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162787 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592788 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2789
Ryan Sleevib8d7ea02018-05-07 20:01:012790 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162791 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012792 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162793 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592794
bnc691fda62016-08-12 00:43:162795 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592796 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582797 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592798
2799 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162800 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592801 ASSERT_FALSE(endpoint.address().empty());
2802 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2803
2804 resolver->rules()->ClearRules();
2805 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2806
2807 TestCompletionCallback callback2;
2808
bnc691fda62016-08-12 00:43:162809 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592810 AuthCredentials(kFoo, kBar), callback2.callback())));
2811
2812 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162813 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592814 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2815 // The load timing after restart should have a new socket ID, and times after
2816 // those of the first load timing.
2817 EXPECT_LE(load_timing_info1.receive_headers_end,
2818 load_timing_info2.connect_timing.connect_start);
2819 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2820
Ryan Sleevib8d7ea02018-05-07 20:01:012821 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162822 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012823 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162824 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592825
bnc691fda62016-08-12 00:43:162826 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592827 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582828 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592829 EXPECT_EQ(100, response->headers->GetContentLength());
2830
bnc691fda62016-08-12 00:43:162831 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592832 ASSERT_FALSE(endpoint.address().empty());
2833 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2834}
2835
David Benjamin83ddfb32018-03-30 01:07:522836// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2837// will eventually give up.
2838TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2839 HttpRequestInfo request;
2840 request.method = "GET";
2841 request.url = GURL("http://www.example.org/");
2842 request.traffic_annotation =
2843 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2844
2845 TestNetLog log;
2846 session_deps_.net_log = &log;
2847 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2848 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2849
2850 MockWrite data_writes[] = {
2851 MockWrite("GET / HTTP/1.1\r\n"
2852 "Host: www.example.org\r\n"
2853 "Connection: keep-alive\r\n\r\n"),
2854 };
2855
2856 MockRead data_reads[] = {
2857 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2858 // Give a couple authenticate options (only the middle one is actually
2859 // supported).
2860 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2861 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2862 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2863 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2864 // Large content-length -- won't matter, as connection will be reset.
2865 MockRead("Content-Length: 10000\r\n\r\n"),
2866 MockRead(SYNCHRONOUS, ERR_FAILED),
2867 };
2868
2869 // After calling trans->RestartWithAuth(), this is the request we should
2870 // be issuing -- the final header line contains the credentials.
2871 MockWrite data_writes_restart[] = {
2872 MockWrite("GET / HTTP/1.1\r\n"
2873 "Host: www.example.org\r\n"
2874 "Connection: keep-alive\r\n"
2875 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2876 };
2877
Ryan Sleevib8d7ea02018-05-07 20:01:012878 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522879 session_deps_.socket_factory->AddSocketDataProvider(&data);
2880
2881 TestCompletionCallback callback;
2882 int rv = callback.GetResult(
2883 trans.Start(&request, callback.callback(), NetLogWithSource()));
2884
2885 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2886 for (int i = 0; i < 32; i++) {
2887 // Check the previous response was a 401.
2888 EXPECT_THAT(rv, IsOk());
2889 const HttpResponseInfo* response = trans.GetResponseInfo();
2890 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582891 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522892
2893 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012894 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522895 session_deps_.socket_factory->AddSocketDataProvider(
2896 data_restarts.back().get());
2897 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2898 callback.callback()));
2899 }
2900
2901 // After too many tries, the transaction should have given up.
2902 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2903}
2904
bncd16676a2016-07-20 16:23:012905TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462906 HttpRequestInfo request;
2907 request.method = "GET";
bncce36dca22015-04-21 22:11:232908 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292909 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:102910 request.traffic_annotation =
2911 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462912
danakj1fd259a02016-04-16 03:17:092913 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162914 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272915
[email protected]861fcd52009-08-26 02:33:462916 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232917 MockWrite(
2918 "GET / HTTP/1.1\r\n"
2919 "Host: www.example.org\r\n"
2920 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462921 };
2922
2923 MockRead data_reads[] = {
2924 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2925 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2926 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2927 // Large content-length -- won't matter, as connection will be reset.
2928 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062929 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462930 };
2931
Ryan Sleevib8d7ea02018-05-07 20:01:012932 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072933 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412934 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462935
tfarina42834112016-09-22 13:38:202936 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012937 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462938
2939 rv = callback.WaitForResult();
2940 EXPECT_EQ(0, rv);
2941
Ryan Sleevib8d7ea02018-05-07 20:01:012942 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162943 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012944 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162945 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192946
bnc691fda62016-08-12 00:43:162947 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522948 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582949 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462950}
2951
[email protected]2d2697f92009-02-18 21:00:322952// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2953// connection.
bncd16676a2016-07-20 16:23:012954TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182955 // On the second pass, the body read of the auth challenge is synchronous, so
2956 // IsConnectedAndIdle returns false. The socket should still be drained and
2957 // reused. See http://crbug.com/544255.
2958 for (int i = 0; i < 2; ++i) {
2959 HttpRequestInfo request;
2960 request.method = "GET";
2961 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102962 request.traffic_annotation =
2963 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322964
mmenkecc2298e2015-12-07 18:20:182965 TestNetLog log;
2966 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092967 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272968
mmenkecc2298e2015-12-07 18:20:182969 MockWrite data_writes[] = {
2970 MockWrite(ASYNC, 0,
2971 "GET / HTTP/1.1\r\n"
2972 "Host: www.example.org\r\n"
2973 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322974
bnc691fda62016-08-12 00:43:162975 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182976 // be issuing -- the final header line contains the credentials.
2977 MockWrite(ASYNC, 6,
2978 "GET / HTTP/1.1\r\n"
2979 "Host: www.example.org\r\n"
2980 "Connection: keep-alive\r\n"
2981 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2982 };
[email protected]2d2697f92009-02-18 21:00:322983
mmenkecc2298e2015-12-07 18:20:182984 MockRead data_reads[] = {
2985 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2986 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2987 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2988 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2989 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322990
mmenkecc2298e2015-12-07 18:20:182991 // Lastly, the server responds with the actual content.
2992 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2993 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2994 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2995 MockRead(ASYNC, 10, "Hello"),
2996 };
[email protected]2d2697f92009-02-18 21:00:322997
Ryan Sleevib8d7ea02018-05-07 20:01:012998 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182999 data.set_busy_before_sync_reads(true);
3000 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:463001
mmenkecc2298e2015-12-07 18:20:183002 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323003
bnc691fda62016-08-12 00:43:163004 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203005 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013006 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323007
mmenkecc2298e2015-12-07 18:20:183008 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:163009 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:183010 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:323011
bnc691fda62016-08-12 00:43:163012 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183013 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583014 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323015
mmenkecc2298e2015-12-07 18:20:183016 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:253017
bnc691fda62016-08-12 00:43:163018 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3019 callback2.callback());
robpercival214763f2016-07-01 23:27:013020 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323021
mmenkecc2298e2015-12-07 18:20:183022 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:163023 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:183024 TestLoadTimingReused(load_timing_info2);
3025 // The load timing after restart should have the same socket ID, and times
3026 // those of the first load timing.
3027 EXPECT_LE(load_timing_info1.receive_headers_end,
3028 load_timing_info2.send_start);
3029 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:323030
bnc691fda62016-08-12 00:43:163031 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183032 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583033 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:183034 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323035
mmenkecc2298e2015-12-07 18:20:183036 std::string response_data;
bnc691fda62016-08-12 00:43:163037 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:323038
Ryan Sleevib8d7ea02018-05-07 20:01:013039 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163040 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013041 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163042 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:183043 }
[email protected]2d2697f92009-02-18 21:00:323044}
3045
3046// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3047// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:013048TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:423049 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323050 request.method = "GET";
bncce36dca22015-04-21 22:11:233051 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103052 request.traffic_annotation =
3053 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323054
danakj1fd259a02016-04-16 03:17:093055 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273056
[email protected]2d2697f92009-02-18 21:00:323057 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163058 MockWrite("GET / HTTP/1.1\r\n"
3059 "Host: www.example.org\r\n"
3060 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323061
bnc691fda62016-08-12 00:43:163062 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233063 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163064 MockWrite("GET / HTTP/1.1\r\n"
3065 "Host: www.example.org\r\n"
3066 "Connection: keep-alive\r\n"
3067 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323068 };
3069
[email protected]2d2697f92009-02-18 21:00:323070 MockRead data_reads1[] = {
3071 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3072 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313073 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323074
3075 // Lastly, the server responds with the actual content.
3076 MockRead("HTTP/1.1 200 OK\r\n"),
3077 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503078 MockRead("Content-Length: 5\r\n\r\n"),
3079 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323080 };
3081
[email protected]2d0a4f92011-05-05 16:38:463082 // An incorrect reconnect would cause this to be read.
3083 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063084 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463085 };
3086
Ryan Sleevib8d7ea02018-05-07 20:01:013087 StaticSocketDataProvider data1(data_reads1, data_writes1);
3088 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073089 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3090 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323091
[email protected]49639fa2011-12-20 23:22:413092 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323093
bnc691fda62016-08-12 00:43:163094 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203095 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013096 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323097
3098 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013099 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323100
bnc691fda62016-08-12 00:43:163101 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523102 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583103 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323104
[email protected]49639fa2011-12-20 23:22:413105 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323106
bnc691fda62016-08-12 00:43:163107 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013108 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323109
3110 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013111 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323112
bnc691fda62016-08-12 00:43:163113 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523114 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583115 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503116 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323117}
3118
3119// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3120// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013121TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423122 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323123 request.method = "GET";
bncce36dca22015-04-21 22:11:233124 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103125 request.traffic_annotation =
3126 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323127
danakj1fd259a02016-04-16 03:17:093128 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273129
[email protected]2d2697f92009-02-18 21:00:323130 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163131 MockWrite("GET / HTTP/1.1\r\n"
3132 "Host: www.example.org\r\n"
3133 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323134
bnc691fda62016-08-12 00:43:163135 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233136 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163137 MockWrite("GET / HTTP/1.1\r\n"
3138 "Host: www.example.org\r\n"
3139 "Connection: keep-alive\r\n"
3140 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323141 };
3142
3143 // Respond with 5 kb of response body.
3144 std::string large_body_string("Unauthorized");
3145 large_body_string.append(5 * 1024, ' ');
3146 large_body_string.append("\r\n");
3147
3148 MockRead data_reads1[] = {
3149 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3150 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3151 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3152 // 5134 = 12 + 5 * 1024 + 2
3153 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063154 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323155
3156 // Lastly, the server responds with the actual content.
3157 MockRead("HTTP/1.1 200 OK\r\n"),
3158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503159 MockRead("Content-Length: 5\r\n\r\n"),
3160 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323161 };
3162
[email protected]2d0a4f92011-05-05 16:38:463163 // An incorrect reconnect would cause this to be read.
3164 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063165 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463166 };
3167
Ryan Sleevib8d7ea02018-05-07 20:01:013168 StaticSocketDataProvider data1(data_reads1, data_writes1);
3169 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073170 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3171 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323172
[email protected]49639fa2011-12-20 23:22:413173 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323174
bnc691fda62016-08-12 00:43:163175 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203176 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013177 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323178
3179 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013180 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323181
bnc691fda62016-08-12 00:43:163182 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523183 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583184 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323185
[email protected]49639fa2011-12-20 23:22:413186 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323187
bnc691fda62016-08-12 00:43:163188 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013189 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323190
3191 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013192 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323193
bnc691fda62016-08-12 00:43:163194 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523195 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583196 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503197 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323198}
3199
3200// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313201// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013202TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313203 HttpRequestInfo request;
3204 request.method = "GET";
bncce36dca22015-04-21 22:11:233205 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103206 request.traffic_annotation =
3207 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313208
danakj1fd259a02016-04-16 03:17:093209 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273210
[email protected]11203f012009-11-12 23:02:313211 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233212 MockWrite(
3213 "GET / HTTP/1.1\r\n"
3214 "Host: www.example.org\r\n"
3215 "Connection: keep-alive\r\n\r\n"),
3216 // This simulates the seemingly successful write to a closed connection
3217 // if the bug is not fixed.
3218 MockWrite(
3219 "GET / HTTP/1.1\r\n"
3220 "Host: www.example.org\r\n"
3221 "Connection: keep-alive\r\n"
3222 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313223 };
3224
3225 MockRead data_reads1[] = {
3226 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3227 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3228 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3229 MockRead("Content-Length: 14\r\n\r\n"),
3230 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063231 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313232 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063233 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313234 };
3235
bnc691fda62016-08-12 00:43:163236 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313237 // be issuing -- the final header line contains the credentials.
3238 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233239 MockWrite(
3240 "GET / HTTP/1.1\r\n"
3241 "Host: www.example.org\r\n"
3242 "Connection: keep-alive\r\n"
3243 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313244 };
3245
3246 // Lastly, the server responds with the actual content.
3247 MockRead data_reads2[] = {
3248 MockRead("HTTP/1.1 200 OK\r\n"),
3249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503250 MockRead("Content-Length: 5\r\n\r\n"),
3251 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313252 };
3253
Ryan Sleevib8d7ea02018-05-07 20:01:013254 StaticSocketDataProvider data1(data_reads1, data_writes1);
3255 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073256 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3257 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313258
[email protected]49639fa2011-12-20 23:22:413259 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313260
bnc691fda62016-08-12 00:43:163261 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203262 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013263 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313264
3265 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013266 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313267
bnc691fda62016-08-12 00:43:163268 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523269 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583270 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313271
[email protected]49639fa2011-12-20 23:22:413272 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313273
bnc691fda62016-08-12 00:43:163274 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013275 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313276
3277 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013278 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313279
bnc691fda62016-08-12 00:43:163280 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523281 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583282 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503283 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313284}
3285
[email protected]394816e92010-08-03 07:38:593286// Test the request-challenge-retry sequence for basic auth, over a connection
3287// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013288TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013289 HttpRequestInfo request;
3290 request.method = "GET";
bncce36dca22015-04-21 22:11:233291 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013292 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293293 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103294 request.traffic_annotation =
3295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013296
3297 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593298 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493299 ProxyResolutionService::CreateFixedFromPacResult(
3300 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513301 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013302 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093303 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013304
3305 // Since we have proxy, should try to establish tunnel.
3306 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543307 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173308 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543309 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013310 };
3311
mmenkee71e15332015-10-07 16:39:543312 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013313 // connection.
3314 MockRead data_reads1[] = {
3315 // No credentials.
3316 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3317 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543318 };
ttuttle34f63b52015-03-05 04:33:013319
mmenkee71e15332015-10-07 16:39:543320 // Since the first connection couldn't be reused, need to establish another
3321 // once given credentials.
3322 MockWrite data_writes2[] = {
3323 // After calling trans->RestartWithAuth(), this is the request we should
3324 // be issuing -- the final header line contains the credentials.
3325 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173326 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543327 "Proxy-Connection: keep-alive\r\n"
3328 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3329
3330 MockWrite("GET / HTTP/1.1\r\n"
3331 "Host: www.example.org\r\n"
3332 "Connection: keep-alive\r\n\r\n"),
3333 };
3334
3335 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013336 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3337
3338 MockRead("HTTP/1.1 200 OK\r\n"),
3339 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3340 MockRead("Content-Length: 5\r\n\r\n"),
3341 MockRead(SYNCHRONOUS, "hello"),
3342 };
3343
Ryan Sleevib8d7ea02018-05-07 20:01:013344 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013345 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013346 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543347 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013348 SSLSocketDataProvider ssl(ASYNC, OK);
3349 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3350
3351 TestCompletionCallback callback1;
3352
bnc87dcefc2017-05-25 12:47:583353 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193354 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013355
3356 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013357 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013358
3359 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013360 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:463361 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:013362 log.GetEntries(&entries);
3363 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003364 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3365 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013366 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003367 entries, pos,
3368 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3369 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013370
3371 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523372 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013373 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523374 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013375 EXPECT_EQ(407, response->headers->response_code());
3376 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583377 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013378
3379 LoadTimingInfo load_timing_info;
3380 // CONNECT requests and responses are handled at the connect job level, so
3381 // the transaction does not yet have a connection.
3382 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3383
3384 TestCompletionCallback callback2;
3385
3386 rv =
3387 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013388 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013389
3390 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013391 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013392
3393 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523394 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013395
3396 EXPECT_TRUE(response->headers->IsKeepAlive());
3397 EXPECT_EQ(200, response->headers->response_code());
3398 EXPECT_EQ(5, response->headers->GetContentLength());
3399 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3400
3401 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583402 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013403
3404 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3405 TestLoadTimingNotReusedWithPac(load_timing_info,
3406 CONNECT_TIMING_HAS_SSL_TIMES);
3407
3408 trans.reset();
3409 session->CloseAllConnections();
3410}
3411
3412// Test the request-challenge-retry sequence for basic auth, over a connection
3413// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013414TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593415 HttpRequestInfo request;
3416 request.method = "GET";
bncce36dca22015-04-21 22:11:233417 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593418 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293419 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103420 request.traffic_annotation =
3421 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593422
[email protected]cb9bf6ca2011-01-28 13:15:273423 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593424 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493425 ProxyResolutionService::CreateFixedFromPacResult(
3426 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513427 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073428 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093429 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273430
[email protected]394816e92010-08-03 07:38:593431 // Since we have proxy, should try to establish tunnel.
3432 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543433 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173434 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543435 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113436 };
3437
mmenkee71e15332015-10-07 16:39:543438 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083439 // connection.
3440 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543441 // No credentials.
3442 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3443 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3444 MockRead("Proxy-Connection: close\r\n\r\n"),
3445 };
mmenkee0b5c882015-08-26 20:29:113446
mmenkee71e15332015-10-07 16:39:543447 MockWrite data_writes2[] = {
3448 // After calling trans->RestartWithAuth(), this is the request we should
3449 // be issuing -- the final header line contains the credentials.
3450 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173451 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543452 "Proxy-Connection: keep-alive\r\n"
3453 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083454
mmenkee71e15332015-10-07 16:39:543455 MockWrite("GET / HTTP/1.1\r\n"
3456 "Host: www.example.org\r\n"
3457 "Connection: keep-alive\r\n\r\n"),
3458 };
3459
3460 MockRead data_reads2[] = {
3461 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3462
3463 MockRead("HTTP/1.1 200 OK\r\n"),
3464 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3465 MockRead("Content-Length: 5\r\n\r\n"),
3466 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593467 };
3468
Ryan Sleevib8d7ea02018-05-07 20:01:013469 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073470 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013471 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543472 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063473 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073474 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593475
[email protected]49639fa2011-12-20 23:22:413476 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593477
bnc87dcefc2017-05-25 12:47:583478 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193479 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503480
[email protected]49639fa2011-12-20 23:22:413481 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013482 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593483
3484 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013485 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:463486 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403487 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:593488 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003489 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3490 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593491 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403492 entries, pos,
mikecirone8b85c432016-09-08 19:11:003493 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3494 NetLogEventPhase::NONE);
[email protected]394816e92010-08-03 07:38:593495
3496 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523497 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013498 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523499 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:593500 EXPECT_EQ(407, response->headers->response_code());
3501 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583502 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]394816e92010-08-03 07:38:593503
[email protected]029c83b62013-01-24 05:28:203504 LoadTimingInfo load_timing_info;
3505 // CONNECT requests and responses are handled at the connect job level, so
3506 // the transaction does not yet have a connection.
3507 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3508
[email protected]49639fa2011-12-20 23:22:413509 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:593510
[email protected]49639fa2011-12-20 23:22:413511 rv = trans->RestartWithAuth(
3512 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013513 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593514
3515 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013516 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:593517
3518 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523519 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:593520
3521 EXPECT_TRUE(response->headers->IsKeepAlive());
3522 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:503523 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:593524 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3525
3526 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583527 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503528
[email protected]029c83b62013-01-24 05:28:203529 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3530 TestLoadTimingNotReusedWithPac(load_timing_info,
3531 CONNECT_TIMING_HAS_SSL_TIMES);
3532
[email protected]0b0bf032010-09-21 18:08:503533 trans.reset();
[email protected]102e27c2011-02-23 01:01:313534 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:593535}
3536
[email protected]11203f012009-11-12 23:02:313537// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:013538// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013539TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:233540 // On the second pass, the body read of the auth challenge is synchronous, so
3541 // IsConnectedAndIdle returns false. The socket should still be drained and
3542 // reused. See http://crbug.com/544255.
3543 for (int i = 0; i < 2; ++i) {
3544 HttpRequestInfo request;
3545 request.method = "GET";
3546 request.url = GURL("https://www.example.org/");
3547 // Ensure that proxy authentication is attempted even
3548 // when the no authentication data flag is set.
3549 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103550 request.traffic_annotation =
3551 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013552
mmenked39192ee2015-12-09 00:57:233553 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593554 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493555 ProxyResolutionService::CreateFixed("myproxy:70",
3556 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233557 BoundTestNetLog log;
3558 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093559 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013560
bnc691fda62016-08-12 00:43:163561 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013562
mmenked39192ee2015-12-09 00:57:233563 // Since we have proxy, should try to establish tunnel.
3564 MockWrite data_writes1[] = {
3565 MockWrite(ASYNC, 0,
3566 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3567 "Host: www.example.org:443\r\n"
3568 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013569
bnc691fda62016-08-12 00:43:163570 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233571 // be issuing -- the final header line contains the credentials.
3572 MockWrite(ASYNC, 3,
3573 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3574 "Host: www.example.org:443\r\n"
3575 "Proxy-Connection: keep-alive\r\n"
3576 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3577 };
ttuttle34f63b52015-03-05 04:33:013578
mmenked39192ee2015-12-09 00:57:233579 // The proxy responds to the connect with a 407, using a persistent
3580 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3581 MockRead data_reads1[] = {
3582 // No credentials.
3583 MockRead(ASYNC, 1,
3584 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3585 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3586 "Proxy-Connection: keep-alive\r\n"
3587 "Content-Length: 10\r\n\r\n"),
3588 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013589
mmenked39192ee2015-12-09 00:57:233590 // Wrong credentials (wrong password).
3591 MockRead(ASYNC, 4,
3592 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3593 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3594 "Proxy-Connection: keep-alive\r\n"
3595 "Content-Length: 10\r\n\r\n"),
3596 // No response body because the test stops reading here.
3597 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3598 };
ttuttle34f63b52015-03-05 04:33:013599
Ryan Sleevib8d7ea02018-05-07 20:01:013600 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233601 data1.set_busy_before_sync_reads(true);
3602 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013603
mmenked39192ee2015-12-09 00:57:233604 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013605
bnc691fda62016-08-12 00:43:163606 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013607 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013608
mmenked39192ee2015-12-09 00:57:233609 TestNetLogEntry::List entries;
3610 log.GetEntries(&entries);
3611 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003612 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3613 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233614 ExpectLogContainsSomewhere(
3615 entries, pos,
mikecirone8b85c432016-09-08 19:11:003616 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3617 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013618
bnc691fda62016-08-12 00:43:163619 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233620 ASSERT_TRUE(response);
3621 ASSERT_TRUE(response->headers);
3622 EXPECT_TRUE(response->headers->IsKeepAlive());
3623 EXPECT_EQ(407, response->headers->response_code());
3624 EXPECT_EQ(10, response->headers->GetContentLength());
3625 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583626 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013627
mmenked39192ee2015-12-09 00:57:233628 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013629
mmenked39192ee2015-12-09 00:57:233630 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163631 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3632 callback2.callback());
robpercival214763f2016-07-01 23:27:013633 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013634
bnc691fda62016-08-12 00:43:163635 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233636 ASSERT_TRUE(response);
3637 ASSERT_TRUE(response->headers);
3638 EXPECT_TRUE(response->headers->IsKeepAlive());
3639 EXPECT_EQ(407, response->headers->response_code());
3640 EXPECT_EQ(10, response->headers->GetContentLength());
3641 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583642 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013643
mmenked39192ee2015-12-09 00:57:233644 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3645 // out of scope.
3646 session->CloseAllConnections();
3647 }
ttuttle34f63b52015-03-05 04:33:013648}
3649
3650// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3651// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013652TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233653 // On the second pass, the body read of the auth challenge is synchronous, so
3654 // IsConnectedAndIdle returns false. The socket should still be drained and
3655 // reused. See http://crbug.com/544255.
3656 for (int i = 0; i < 2; ++i) {
3657 HttpRequestInfo request;
3658 request.method = "GET";
3659 request.url = GURL("https://www.example.org/");
3660 // Ensure that proxy authentication is attempted even
3661 // when the no authentication data flag is set.
3662 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103663 request.traffic_annotation =
3664 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233665
3666 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593667 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493668 ProxyResolutionService::CreateFixed("myproxy:70",
3669 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233670 BoundTestNetLog log;
3671 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093672 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233673
bnc691fda62016-08-12 00:43:163674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233675
3676 // Since we have proxy, should try to establish tunnel.
3677 MockWrite data_writes1[] = {
3678 MockWrite(ASYNC, 0,
3679 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3680 "Host: www.example.org:443\r\n"
3681 "Proxy-Connection: keep-alive\r\n\r\n"),
3682
bnc691fda62016-08-12 00:43:163683 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233684 // be issuing -- the final header line contains the credentials.
3685 MockWrite(ASYNC, 3,
3686 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3687 "Host: www.example.org:443\r\n"
3688 "Proxy-Connection: keep-alive\r\n"
3689 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3690 };
3691
3692 // The proxy responds to the connect with a 407, using a persistent
3693 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3694 MockRead data_reads1[] = {
3695 // No credentials.
3696 MockRead(ASYNC, 1,
3697 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3698 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3699 "Content-Length: 10\r\n\r\n"),
3700 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3701
3702 // Wrong credentials (wrong password).
3703 MockRead(ASYNC, 4,
3704 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3705 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3706 "Content-Length: 10\r\n\r\n"),
3707 // No response body because the test stops reading here.
3708 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3709 };
3710
Ryan Sleevib8d7ea02018-05-07 20:01:013711 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233712 data1.set_busy_before_sync_reads(true);
3713 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3714
3715 TestCompletionCallback callback1;
3716
bnc691fda62016-08-12 00:43:163717 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013718 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233719
3720 TestNetLogEntry::List entries;
3721 log.GetEntries(&entries);
3722 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003723 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3724 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233725 ExpectLogContainsSomewhere(
3726 entries, pos,
mikecirone8b85c432016-09-08 19:11:003727 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3728 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233729
bnc691fda62016-08-12 00:43:163730 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233731 ASSERT_TRUE(response);
3732 ASSERT_TRUE(response->headers);
3733 EXPECT_TRUE(response->headers->IsKeepAlive());
3734 EXPECT_EQ(407, response->headers->response_code());
3735 EXPECT_EQ(10, response->headers->GetContentLength());
3736 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583737 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503738 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233739
3740 TestCompletionCallback callback2;
3741
3742 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163743 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3744 callback2.callback());
robpercival214763f2016-07-01 23:27:013745 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233746
bnc691fda62016-08-12 00:43:163747 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233748 ASSERT_TRUE(response);
3749 ASSERT_TRUE(response->headers);
3750 EXPECT_TRUE(response->headers->IsKeepAlive());
3751 EXPECT_EQ(407, response->headers->response_code());
3752 EXPECT_EQ(10, response->headers->GetContentLength());
3753 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583754 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503755 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233756
3757 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3758 // out of scope.
3759 session->CloseAllConnections();
3760 }
3761}
3762
3763// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3764// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3765// the case the server sends extra data on the original socket, so it can't be
3766// reused.
bncd16676a2016-07-20 16:23:013767TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273768 HttpRequestInfo request;
3769 request.method = "GET";
bncce36dca22015-04-21 22:11:233770 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273771 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293772 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103773 request.traffic_annotation =
3774 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273775
[email protected]2d2697f92009-02-18 21:00:323776 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593777 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493778 ProxyResolutionService::CreateFixedFromPacResult(
3779 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513780 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073781 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093782 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323783
[email protected]2d2697f92009-02-18 21:00:323784 // Since we have proxy, should try to establish tunnel.
3785 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233786 MockWrite(ASYNC, 0,
3787 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173788 "Host: www.example.org:443\r\n"
3789 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233790 };
[email protected]2d2697f92009-02-18 21:00:323791
mmenked39192ee2015-12-09 00:57:233792 // The proxy responds to the connect with a 407, using a persistent, but sends
3793 // extra data, so the socket cannot be reused.
3794 MockRead data_reads1[] = {
3795 // No credentials.
3796 MockRead(ASYNC, 1,
3797 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3798 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3799 "Content-Length: 10\r\n\r\n"),
3800 MockRead(SYNCHRONOUS, 2, "0123456789"),
3801 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3802 };
3803
3804 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233805 // After calling trans->RestartWithAuth(), this is the request we should
3806 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233807 MockWrite(ASYNC, 0,
3808 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173809 "Host: www.example.org:443\r\n"
3810 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233811 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3812
3813 MockWrite(ASYNC, 2,
3814 "GET / HTTP/1.1\r\n"
3815 "Host: www.example.org\r\n"
3816 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323817 };
3818
mmenked39192ee2015-12-09 00:57:233819 MockRead data_reads2[] = {
3820 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323821
mmenked39192ee2015-12-09 00:57:233822 MockRead(ASYNC, 3,
3823 "HTTP/1.1 200 OK\r\n"
3824 "Content-Type: text/html; charset=iso-8859-1\r\n"
3825 "Content-Length: 5\r\n\r\n"),
3826 // No response body because the test stops reading here.
3827 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323828 };
3829
Ryan Sleevib8d7ea02018-05-07 20:01:013830 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233831 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073832 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013833 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233834 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3835 SSLSocketDataProvider ssl(ASYNC, OK);
3836 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323837
[email protected]49639fa2011-12-20 23:22:413838 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323839
bnc87dcefc2017-05-25 12:47:583840 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193841 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323842
mmenked39192ee2015-12-09 00:57:233843 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013844 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233845
mmenke43758e62015-05-04 21:09:463846 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403847 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:393848 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003849 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3850 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393851 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403852 entries, pos,
mikecirone8b85c432016-09-08 19:11:003853 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3854 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323855
[email protected]1c773ea12009-04-28 19:58:423856 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243857 ASSERT_TRUE(response);
3858 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323859 EXPECT_TRUE(response->headers->IsKeepAlive());
3860 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423861 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583862 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323863
mmenked39192ee2015-12-09 00:57:233864 LoadTimingInfo load_timing_info;
3865 // CONNECT requests and responses are handled at the connect job level, so
3866 // the transaction does not yet have a connection.
3867 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3868
[email protected]49639fa2011-12-20 23:22:413869 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323870
mmenked39192ee2015-12-09 00:57:233871 rv =
3872 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013873 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323874
[email protected]2d2697f92009-02-18 21:00:323875 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233876 EXPECT_EQ(200, response->headers->response_code());
3877 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423878 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133879
mmenked39192ee2015-12-09 00:57:233880 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583881 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233882
3883 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3884 TestLoadTimingNotReusedWithPac(load_timing_info,
3885 CONNECT_TIMING_HAS_SSL_TIMES);
3886
3887 trans.reset();
[email protected]102e27c2011-02-23 01:01:313888 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323889}
3890
mmenkee71e15332015-10-07 16:39:543891// Test the case a proxy closes a socket while the challenge body is being
3892// drained.
bncd16676a2016-07-20 16:23:013893TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543894 HttpRequestInfo request;
3895 request.method = "GET";
3896 request.url = GURL("https://www.example.org/");
3897 // Ensure that proxy authentication is attempted even
3898 // when the no authentication data flag is set.
3899 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103900 request.traffic_annotation =
3901 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543902
3903 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493904 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3905 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093906 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543907
bnc691fda62016-08-12 00:43:163908 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543909
3910 // Since we have proxy, should try to establish tunnel.
3911 MockWrite data_writes1[] = {
3912 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173913 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543914 "Proxy-Connection: keep-alive\r\n\r\n"),
3915 };
3916
3917 // The proxy responds to the connect with a 407, using a persistent
3918 // connection.
3919 MockRead data_reads1[] = {
3920 // No credentials.
3921 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3922 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3923 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3924 // Server hands up in the middle of the body.
3925 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3926 };
3927
3928 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163929 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543930 // be issuing -- the final header line contains the credentials.
3931 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173932 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543933 "Proxy-Connection: keep-alive\r\n"
3934 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3935
3936 MockWrite("GET / HTTP/1.1\r\n"
3937 "Host: www.example.org\r\n"
3938 "Connection: keep-alive\r\n\r\n"),
3939 };
3940
3941 MockRead data_reads2[] = {
3942 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3943
3944 MockRead("HTTP/1.1 200 OK\r\n"),
3945 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3946 MockRead("Content-Length: 5\r\n\r\n"),
3947 MockRead(SYNCHRONOUS, "hello"),
3948 };
3949
Ryan Sleevib8d7ea02018-05-07 20:01:013950 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543951 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013952 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543953 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3954 SSLSocketDataProvider ssl(ASYNC, OK);
3955 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3956
3957 TestCompletionCallback callback;
3958
tfarina42834112016-09-22 13:38:203959 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013960 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543961
bnc691fda62016-08-12 00:43:163962 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543963 ASSERT_TRUE(response);
3964 ASSERT_TRUE(response->headers);
3965 EXPECT_TRUE(response->headers->IsKeepAlive());
3966 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583967 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543968
bnc691fda62016-08-12 00:43:163969 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013970 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543971
bnc691fda62016-08-12 00:43:163972 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543973 ASSERT_TRUE(response);
3974 ASSERT_TRUE(response->headers);
3975 EXPECT_TRUE(response->headers->IsKeepAlive());
3976 EXPECT_EQ(200, response->headers->response_code());
3977 std::string body;
bnc691fda62016-08-12 00:43:163978 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543979 EXPECT_EQ("hello", body);
3980}
3981
[email protected]a8e9b162009-03-12 00:06:443982// Test that we don't read the response body when we fail to establish a tunnel,
3983// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013984TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273985 HttpRequestInfo request;
3986 request.method = "GET";
bncce36dca22015-04-21 22:11:233987 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103988 request.traffic_annotation =
3989 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273990
[email protected]a8e9b162009-03-12 00:06:443991 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493992 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3993 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443994
danakj1fd259a02016-04-16 03:17:093995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443996
bnc691fda62016-08-12 00:43:163997 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443998
[email protected]a8e9b162009-03-12 00:06:443999 // Since we have proxy, should try to establish tunnel.
4000 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174001 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4002 "Host: www.example.org:443\r\n"
4003 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:444004 };
4005
4006 // The proxy responds to the connect with a 407.
4007 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:244008 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4009 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4010 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234011 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:244012 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:444013 };
4014
Ryan Sleevib8d7ea02018-05-07 20:01:014015 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:074016 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:444017
[email protected]49639fa2011-12-20 23:22:414018 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:444019
tfarina42834112016-09-22 13:38:204020 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014021 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:444022
4023 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014024 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:444025
bnc691fda62016-08-12 00:43:164026 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244027 ASSERT_TRUE(response);
4028 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:444029 EXPECT_TRUE(response->headers->IsKeepAlive());
4030 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424031 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:444032
4033 std::string response_data;
bnc691fda62016-08-12 00:43:164034 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014035 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:184036
4037 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:314038 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:444039}
4040
ttuttle7933c112015-01-06 00:55:244041// Test that we don't pass extraneous headers from the proxy's response to the
4042// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014043TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244044 HttpRequestInfo request;
4045 request.method = "GET";
bncce36dca22015-04-21 22:11:234046 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104047 request.traffic_annotation =
4048 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244049
4050 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:494051 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4052 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244053
danakj1fd259a02016-04-16 03:17:094054 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244055
bnc691fda62016-08-12 00:43:164056 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244057
4058 // Since we have proxy, should try to establish tunnel.
4059 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174060 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4061 "Host: www.example.org:443\r\n"
4062 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244063 };
4064
4065 // The proxy responds to the connect with a 407.
4066 MockRead data_reads[] = {
4067 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4068 MockRead("X-Foo: bar\r\n"),
4069 MockRead("Set-Cookie: foo=bar\r\n"),
4070 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4071 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234072 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244073 };
4074
Ryan Sleevib8d7ea02018-05-07 20:01:014075 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244076 session_deps_.socket_factory->AddSocketDataProvider(&data);
4077
4078 TestCompletionCallback callback;
4079
tfarina42834112016-09-22 13:38:204080 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014081 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244082
4083 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014084 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244085
bnc691fda62016-08-12 00:43:164086 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244087 ASSERT_TRUE(response);
4088 ASSERT_TRUE(response->headers);
4089 EXPECT_TRUE(response->headers->IsKeepAlive());
4090 EXPECT_EQ(407, response->headers->response_code());
4091 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4092 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4093 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4094
4095 std::string response_data;
bnc691fda62016-08-12 00:43:164096 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014097 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244098
4099 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4100 session->CloseAllConnections();
4101}
4102
[email protected]8fdbcd22010-05-05 02:54:524103// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4104// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014105TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524106 HttpRequestInfo request;
4107 request.method = "GET";
bncce36dca22015-04-21 22:11:234108 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104109 request.traffic_annotation =
4110 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524111
[email protected]cb9bf6ca2011-01-28 13:15:274112 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094113 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164114 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274115
[email protected]8fdbcd22010-05-05 02:54:524116 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234117 MockWrite(
4118 "GET / HTTP/1.1\r\n"
4119 "Host: www.example.org\r\n"
4120 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524121 };
4122
4123 MockRead data_reads1[] = {
4124 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4125 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4126 // Large content-length -- won't matter, as connection will be reset.
4127 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064128 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524129 };
4130
Ryan Sleevib8d7ea02018-05-07 20:01:014131 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074132 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524133
[email protected]49639fa2011-12-20 23:22:414134 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524135
tfarina42834112016-09-22 13:38:204136 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014137 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524138
4139 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014140 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524141}
4142
[email protected]7a67a8152010-11-05 18:31:104143// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4144// through a non-authenticating proxy. The request should fail with
4145// ERR_UNEXPECTED_PROXY_AUTH.
4146// Note that it is impossible to detect if an HTTP server returns a 407 through
4147// a non-authenticating proxy - there is nothing to indicate whether the
4148// response came from the proxy or the server, so it is treated as if the proxy
4149// issued the challenge.
bncd16676a2016-07-20 16:23:014150TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274151 HttpRequestInfo request;
4152 request.method = "GET";
bncce36dca22015-04-21 22:11:234153 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104154 request.traffic_annotation =
4155 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274156
Ramin Halavatica8d5252018-03-12 05:33:494157 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4158 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514159 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074160 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094161 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104162
[email protected]7a67a8152010-11-05 18:31:104163 // Since we have proxy, should try to establish tunnel.
4164 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174165 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4166 "Host: www.example.org:443\r\n"
4167 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104168
rsleevidb16bb02015-11-12 23:47:174169 MockWrite("GET / HTTP/1.1\r\n"
4170 "Host: www.example.org\r\n"
4171 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104172 };
4173
4174 MockRead data_reads1[] = {
4175 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4176
4177 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4178 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4179 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064180 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104181 };
4182
Ryan Sleevib8d7ea02018-05-07 20:01:014183 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074184 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064185 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104187
[email protected]49639fa2011-12-20 23:22:414188 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104189
bnc691fda62016-08-12 00:43:164190 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104191
bnc691fda62016-08-12 00:43:164192 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014193 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104194
4195 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014196 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
mmenke43758e62015-05-04 21:09:464197 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:404198 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:104199 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004200 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4201 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104202 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404203 entries, pos,
mikecirone8b85c432016-09-08 19:11:004204 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4205 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104206}
[email protected]2df19bb2010-08-25 20:13:464207
mmenke2a1781d2015-10-07 19:25:334208// Test a proxy auth scheme that allows default credentials and a proxy server
4209// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014210TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334211 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4212 HttpRequestInfo request;
4213 request.method = "GET";
4214 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104215 request.traffic_annotation =
4216 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334217
4218 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594219 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494220 ProxyResolutionService::CreateFixedFromPacResult(
4221 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334222
Jeremy Roman0579ed62017-08-29 15:56:194223 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334224 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194225 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334226 mock_handler->set_allows_default_credentials(true);
4227 auth_handler_factory->AddMockHandler(mock_handler.release(),
4228 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484229 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334230
4231 // Add NetLog just so can verify load timing information gets a NetLog ID.
4232 NetLog net_log;
4233 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094234 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334235
4236 // Since we have proxy, should try to establish tunnel.
4237 MockWrite data_writes1[] = {
4238 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174239 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334240 "Proxy-Connection: keep-alive\r\n\r\n"),
4241 };
4242
4243 // The proxy responds to the connect with a 407, using a non-persistent
4244 // connection.
4245 MockRead data_reads1[] = {
4246 // No credentials.
4247 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4248 MockRead("Proxy-Authenticate: Mock\r\n"),
4249 MockRead("Proxy-Connection: close\r\n\r\n"),
4250 };
4251
4252 // Since the first connection couldn't be reused, need to establish another
4253 // once given credentials.
4254 MockWrite data_writes2[] = {
4255 // After calling trans->RestartWithAuth(), this is the request we should
4256 // be issuing -- the final header line contains the credentials.
4257 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174258 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334259 "Proxy-Connection: keep-alive\r\n"
4260 "Proxy-Authorization: auth_token\r\n\r\n"),
4261
4262 MockWrite("GET / HTTP/1.1\r\n"
4263 "Host: www.example.org\r\n"
4264 "Connection: keep-alive\r\n\r\n"),
4265 };
4266
4267 MockRead data_reads2[] = {
4268 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4269
4270 MockRead("HTTP/1.1 200 OK\r\n"),
4271 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4272 MockRead("Content-Length: 5\r\n\r\n"),
4273 MockRead(SYNCHRONOUS, "hello"),
4274 };
4275
Ryan Sleevib8d7ea02018-05-07 20:01:014276 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334277 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014278 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334279 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4280 SSLSocketDataProvider ssl(ASYNC, OK);
4281 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4282
bnc87dcefc2017-05-25 12:47:584283 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194284 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334285
4286 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204287 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014288 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334289
4290 const HttpResponseInfo* response = trans->GetResponseInfo();
4291 ASSERT_TRUE(response);
4292 ASSERT_TRUE(response->headers);
4293 EXPECT_FALSE(response->headers->IsKeepAlive());
4294 EXPECT_EQ(407, response->headers->response_code());
4295 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4296 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584297 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334298
4299 LoadTimingInfo load_timing_info;
4300 // CONNECT requests and responses are handled at the connect job level, so
4301 // the transaction does not yet have a connection.
4302 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4303
4304 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014305 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334306 response = trans->GetResponseInfo();
4307 ASSERT_TRUE(response);
4308 ASSERT_TRUE(response->headers);
4309 EXPECT_TRUE(response->headers->IsKeepAlive());
4310 EXPECT_EQ(200, response->headers->response_code());
4311 EXPECT_EQ(5, response->headers->GetContentLength());
4312 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4313
4314 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584315 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334316
4317 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4318 TestLoadTimingNotReusedWithPac(load_timing_info,
4319 CONNECT_TIMING_HAS_SSL_TIMES);
4320
4321 trans.reset();
4322 session->CloseAllConnections();
4323}
4324
4325// Test a proxy auth scheme that allows default credentials and a proxy server
4326// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014327TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334328 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4329 HttpRequestInfo request;
4330 request.method = "GET";
4331 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104332 request.traffic_annotation =
4333 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334334
4335 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594336 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494337 ProxyResolutionService::CreateFixedFromPacResult(
4338 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334339
Jeremy Roman0579ed62017-08-29 15:56:194340 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334341 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194342 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334343 mock_handler->set_allows_default_credentials(true);
4344 auth_handler_factory->AddMockHandler(mock_handler.release(),
4345 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484346 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334347
4348 // Add NetLog just so can verify load timing information gets a NetLog ID.
4349 NetLog net_log;
4350 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094351 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334352
4353 // Should try to establish tunnel.
4354 MockWrite data_writes1[] = {
4355 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174356 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334357 "Proxy-Connection: keep-alive\r\n\r\n"),
4358
4359 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174360 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334361 "Proxy-Connection: keep-alive\r\n"
4362 "Proxy-Authorization: auth_token\r\n\r\n"),
4363 };
4364
4365 // The proxy responds to the connect with a 407, using a non-persistent
4366 // connection.
4367 MockRead data_reads1[] = {
4368 // No credentials.
4369 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4370 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4371 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4372 };
4373
4374 // Since the first connection was closed, need to establish another once given
4375 // credentials.
4376 MockWrite data_writes2[] = {
4377 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174378 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334379 "Proxy-Connection: keep-alive\r\n"
4380 "Proxy-Authorization: auth_token\r\n\r\n"),
4381
4382 MockWrite("GET / HTTP/1.1\r\n"
4383 "Host: www.example.org\r\n"
4384 "Connection: keep-alive\r\n\r\n"),
4385 };
4386
4387 MockRead data_reads2[] = {
4388 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4389
4390 MockRead("HTTP/1.1 200 OK\r\n"),
4391 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4392 MockRead("Content-Length: 5\r\n\r\n"),
4393 MockRead(SYNCHRONOUS, "hello"),
4394 };
4395
Ryan Sleevib8d7ea02018-05-07 20:01:014396 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334397 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014398 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334399 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4400 SSLSocketDataProvider ssl(ASYNC, OK);
4401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4402
bnc87dcefc2017-05-25 12:47:584403 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194404 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334405
4406 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204407 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014408 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334409
4410 const HttpResponseInfo* response = trans->GetResponseInfo();
4411 ASSERT_TRUE(response);
4412 ASSERT_TRUE(response->headers);
4413 EXPECT_TRUE(response->headers->IsKeepAlive());
4414 EXPECT_EQ(407, response->headers->response_code());
4415 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4416 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584417 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334418
4419 LoadTimingInfo load_timing_info;
4420 // CONNECT requests and responses are handled at the connect job level, so
4421 // the transaction does not yet have a connection.
4422 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4423
4424 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014425 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334426
4427 response = trans->GetResponseInfo();
4428 ASSERT_TRUE(response);
4429 ASSERT_TRUE(response->headers);
4430 EXPECT_TRUE(response->headers->IsKeepAlive());
4431 EXPECT_EQ(200, response->headers->response_code());
4432 EXPECT_EQ(5, response->headers->GetContentLength());
4433 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4434
4435 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584436 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334437
4438 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4439 TestLoadTimingNotReusedWithPac(load_timing_info,
4440 CONNECT_TIMING_HAS_SSL_TIMES);
4441
4442 trans.reset();
4443 session->CloseAllConnections();
4444}
4445
4446// Test a proxy auth scheme that allows default credentials and a proxy server
4447// that hangs up when credentials are initially sent, and hangs up again when
4448// they are retried.
bncd16676a2016-07-20 16:23:014449TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334450 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
4451 HttpRequestInfo request;
4452 request.method = "GET";
4453 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104454 request.traffic_annotation =
4455 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334456
4457 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594458 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494459 ProxyResolutionService::CreateFixedFromPacResult(
4460 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334461
Jeremy Roman0579ed62017-08-29 15:56:194462 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334463 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194464 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334465 mock_handler->set_allows_default_credentials(true);
4466 auth_handler_factory->AddMockHandler(mock_handler.release(),
4467 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484468 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334469
4470 // Add NetLog just so can verify load timing information gets a NetLog ID.
4471 NetLog net_log;
4472 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094473 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334474
4475 // Should try to establish tunnel.
4476 MockWrite data_writes1[] = {
4477 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174478 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334479 "Proxy-Connection: keep-alive\r\n\r\n"),
4480
4481 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174482 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334483 "Proxy-Connection: keep-alive\r\n"
4484 "Proxy-Authorization: auth_token\r\n\r\n"),
4485 };
4486
4487 // The proxy responds to the connect with a 407, and then hangs up after the
4488 // second request is sent.
4489 MockRead data_reads1[] = {
4490 // No credentials.
4491 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4492 MockRead("Content-Length: 0\r\n"),
4493 MockRead("Proxy-Connection: keep-alive\r\n"),
4494 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4495 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4496 };
4497
4498 // HttpNetworkTransaction sees a reused connection that was closed with
4499 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
4500 // request.
4501 MockWrite data_writes2[] = {
4502 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174503 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334504 "Proxy-Connection: keep-alive\r\n\r\n"),
4505 };
4506
4507 // The proxy, having had more than enough of us, just hangs up.
4508 MockRead data_reads2[] = {
4509 // No credentials.
4510 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4511 };
4512
Ryan Sleevib8d7ea02018-05-07 20:01:014513 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334514 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014515 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334516 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4517
bnc87dcefc2017-05-25 12:47:584518 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194519 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334520
4521 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204522 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014523 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334524
4525 const HttpResponseInfo* response = trans->GetResponseInfo();
4526 ASSERT_TRUE(response);
4527 ASSERT_TRUE(response->headers);
4528 EXPECT_TRUE(response->headers->IsKeepAlive());
4529 EXPECT_EQ(407, response->headers->response_code());
4530 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4531 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584532 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334533
4534 LoadTimingInfo load_timing_info;
4535 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4536
4537 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014538 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:334539
4540 trans.reset();
4541 session->CloseAllConnections();
4542}
4543
Asanka Herathbc3f8f62018-11-16 23:08:304544// This test exercises an odd edge case where the proxy closes the connection
4545// after the authentication handshake is complete. Presumably this technique is
4546// used in lieu of returning a 403 or 5xx status code when the authentication
4547// succeeds, but the user is not authorized to connect to the destination
4548// server. There's no standard for what a proxy should do to indicate a blocked
4549// site.
4550TEST_F(HttpNetworkTransactionTest,
4551 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
4552 HttpRequestInfo request;
4553 request.method = "GET";
4554 request.url = GURL("https://www.example.org/");
4555 request.traffic_annotation =
4556 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4557
4558 // Configure against proxy server "myproxy:70".
4559 session_deps_.proxy_resolution_service =
4560 ProxyResolutionService::CreateFixedFromPacResult(
4561 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4562
Asanka Herathbc3f8f62018-11-16 23:08:304563 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
4564 auth_handler_factory->set_do_init_from_challenge(true);
4565
4566 // Create two mock AuthHandlers. This is because the transaction gets retried
4567 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
4568 // was a real network error.
4569 //
4570 // The handlers support both default and explicit credentials. The retry
4571 // mentioned above should be able to reuse the default identity. Thus there
4572 // should never be a need to prompt for explicit credentials.
4573 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
4574 mock_handler->set_allows_default_credentials(true);
4575 mock_handler->set_allows_explicit_credentials(true);
4576 mock_handler->set_connection_based(true);
4577 auth_handler_factory->AddMockHandler(mock_handler.release(),
4578 HttpAuth::AUTH_PROXY);
4579 mock_handler = std::make_unique<HttpAuthHandlerMock>();
4580 mock_handler->set_allows_default_credentials(true);
4581 mock_handler->set_allows_explicit_credentials(true);
4582 mock_handler->set_connection_based(true);
4583 auth_handler_factory->AddMockHandler(mock_handler.release(),
4584 HttpAuth::AUTH_PROXY);
4585 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4586
4587 NetLog net_log;
4588 session_deps_.net_log = &net_log;
4589 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4590
4591 // Data for both sockets.
4592 //
4593 // Writes are for the tunnel establishment attempts and the
4594 // authentication handshake.
4595 MockWrite data_writes1[] = {
4596 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4597 "Host: www.example.org:443\r\n"
4598 "Proxy-Connection: keep-alive\r\n\r\n"),
4599
4600 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4601 "Host: www.example.org:443\r\n"
4602 "Proxy-Connection: keep-alive\r\n"
4603 "Proxy-Authorization: auth_token\r\n\r\n"),
4604
4605 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4606 "Host: www.example.org:443\r\n"
4607 "Proxy-Connection: keep-alive\r\n"
4608 "Proxy-Authorization: auth_token\r\n\r\n"),
4609 };
4610
4611 // The server side of the authentication handshake. Note that the response to
4612 // the final CONNECT request is ERR_CONNECTION_CLOSED.
4613 MockRead data_reads1[] = {
4614 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4615 MockRead("Content-Length: 0\r\n"),
4616 MockRead("Proxy-Connection: keep-alive\r\n"),
4617 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4618
4619 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4620 MockRead("Content-Length: 0\r\n"),
4621 MockRead("Proxy-Connection: keep-alive\r\n"),
4622 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
4623
4624 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4625 };
4626
4627 StaticSocketDataProvider data1(data_reads1, data_writes1);
4628 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4629
4630 // The second socket is for the reconnection attempt. Data is identical to the
4631 // first attempt.
4632 StaticSocketDataProvider data2(data_reads1, data_writes1);
4633 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4634
4635 auto trans =
4636 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4637
4638 TestCompletionCallback callback;
4639 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4640
4641 // Two rounds per handshake. After one retry, the error is propagated up the
4642 // stack.
4643 for (int i = 0; i < 4; ++i) {
4644 EXPECT_THAT(callback.GetResult(rv), IsOk());
4645
4646 const HttpResponseInfo* response = trans->GetResponseInfo();
4647 ASSERT_TRUE(response);
4648 ASSERT_TRUE(response->headers);
4649 EXPECT_EQ(407, response->headers->response_code());
4650 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
4651
4652 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4653 }
4654
4655 // One shall be the number thou shalt retry, and the number of the retrying
4656 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
4657 // that thou then proceed to one. Three is right out. Once the number one,
4658 // being the first number, be reached, then lobbest thou thy
4659 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
4660 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
4661
4662 trans.reset();
4663 session->CloseAllConnections();
4664}
4665
mmenke2a1781d2015-10-07 19:25:334666// Test a proxy auth scheme that allows default credentials and a proxy server
4667// that hangs up when credentials are initially sent, and sends a challenge
4668// again they are retried.
bncd16676a2016-07-20 16:23:014669TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334670 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
4671 HttpRequestInfo request;
4672 request.method = "GET";
4673 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104674 request.traffic_annotation =
4675 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334676
4677 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594678 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494679 ProxyResolutionService::CreateFixedFromPacResult(
4680 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334681
Jeremy Roman0579ed62017-08-29 15:56:194682 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334683 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194684 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334685 mock_handler->set_allows_default_credentials(true);
4686 auth_handler_factory->AddMockHandler(mock_handler.release(),
4687 HttpAuth::AUTH_PROXY);
4688 // Add another handler for the second challenge. It supports default
4689 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194690 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334691 mock_handler->set_allows_default_credentials(true);
4692 auth_handler_factory->AddMockHandler(mock_handler.release(),
4693 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484694 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334695
4696 // Add NetLog just so can verify load timing information gets a NetLog ID.
4697 NetLog net_log;
4698 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094699 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334700
4701 // Should try to establish tunnel.
4702 MockWrite data_writes1[] = {
4703 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174704 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334705 "Proxy-Connection: keep-alive\r\n\r\n"),
4706 };
4707
4708 // The proxy responds to the connect with a 407, using a non-persistent
4709 // connection.
4710 MockRead data_reads1[] = {
4711 // No credentials.
4712 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4713 MockRead("Proxy-Authenticate: Mock\r\n"),
4714 MockRead("Proxy-Connection: close\r\n\r\n"),
4715 };
4716
4717 // Since the first connection was closed, need to establish another once given
4718 // credentials.
4719 MockWrite data_writes2[] = {
4720 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174721 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334722 "Proxy-Connection: keep-alive\r\n"
4723 "Proxy-Authorization: auth_token\r\n\r\n"),
4724 };
4725
4726 MockRead data_reads2[] = {
4727 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4728 MockRead("Proxy-Authenticate: Mock\r\n"),
4729 MockRead("Proxy-Connection: close\r\n\r\n"),
4730 };
4731
Ryan Sleevib8d7ea02018-05-07 20:01:014732 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334733 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014734 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334735 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4736 SSLSocketDataProvider ssl(ASYNC, OK);
4737 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4738
bnc87dcefc2017-05-25 12:47:584739 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194740 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334741
4742 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204743 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014744 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334745
4746 const HttpResponseInfo* response = trans->GetResponseInfo();
4747 ASSERT_TRUE(response);
4748 ASSERT_TRUE(response->headers);
4749 EXPECT_EQ(407, response->headers->response_code());
4750 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4751 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584752 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334753
4754 LoadTimingInfo load_timing_info;
4755 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4756
4757 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014758 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334759 response = trans->GetResponseInfo();
4760 ASSERT_TRUE(response);
4761 ASSERT_TRUE(response->headers);
4762 EXPECT_EQ(407, response->headers->response_code());
4763 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584764 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334765
4766 trans.reset();
4767 session->CloseAllConnections();
4768}
4769
asankae2257db2016-10-11 22:03:164770// A more nuanced test than GenerateAuthToken test which asserts that
4771// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
4772// unnecessarily invalidated, and that if the server co-operates, the
4773// authentication handshake can continue with the same scheme but with a
4774// different identity.
4775TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
4776 HttpRequestInfo request;
4777 request.method = "GET";
4778 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104779 request.traffic_annotation =
4780 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:164781
Jeremy Roman0579ed62017-08-29 15:56:194782 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:164783 auth_handler_factory->set_do_init_from_challenge(true);
4784
4785 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:194786 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164787 mock_handler->set_allows_default_credentials(true);
4788 mock_handler->set_allows_explicit_credentials(true);
4789 mock_handler->set_connection_based(true);
4790 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
4791 auth_handler_factory->AddMockHandler(mock_handler.release(),
4792 HttpAuth::AUTH_SERVER);
4793
4794 // Add another handler for the second challenge. It supports default
4795 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194796 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164797 mock_handler->set_allows_default_credentials(true);
4798 mock_handler->set_allows_explicit_credentials(true);
4799 mock_handler->set_connection_based(true);
4800 auth_handler_factory->AddMockHandler(mock_handler.release(),
4801 HttpAuth::AUTH_SERVER);
4802 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4803
4804 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4805
4806 MockWrite data_writes1[] = {
4807 MockWrite("GET / HTTP/1.1\r\n"
4808 "Host: www.example.org\r\n"
4809 "Connection: keep-alive\r\n\r\n"),
4810 };
4811
4812 MockRead data_reads1[] = {
4813 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4814 "WWW-Authenticate: Mock\r\n"
4815 "Connection: keep-alive\r\n\r\n"),
4816 };
4817
4818 // Identical to data_writes1[]. The AuthHandler encounters a
4819 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
4820 // transaction procceds without an authorization header.
4821 MockWrite data_writes2[] = {
4822 MockWrite("GET / HTTP/1.1\r\n"
4823 "Host: www.example.org\r\n"
4824 "Connection: keep-alive\r\n\r\n"),
4825 };
4826
4827 MockRead data_reads2[] = {
4828 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4829 "WWW-Authenticate: Mock\r\n"
4830 "Connection: keep-alive\r\n\r\n"),
4831 };
4832
4833 MockWrite data_writes3[] = {
4834 MockWrite("GET / HTTP/1.1\r\n"
4835 "Host: www.example.org\r\n"
4836 "Connection: keep-alive\r\n"
4837 "Authorization: auth_token\r\n\r\n"),
4838 };
4839
4840 MockRead data_reads3[] = {
4841 MockRead("HTTP/1.1 200 OK\r\n"
4842 "Content-Length: 5\r\n"
4843 "Content-Type: text/plain\r\n"
4844 "Connection: keep-alive\r\n\r\n"
4845 "Hello"),
4846 };
4847
Ryan Sleevib8d7ea02018-05-07 20:01:014848 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:164849 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4850
Ryan Sleevib8d7ea02018-05-07 20:01:014851 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:164852 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4853
Ryan Sleevib8d7ea02018-05-07 20:01:014854 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:164855 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4856
bnc87dcefc2017-05-25 12:47:584857 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194858 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:164859
4860 TestCompletionCallback callback;
4861 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4862 EXPECT_THAT(callback.GetResult(rv), IsOk());
4863
4864 const HttpResponseInfo* response = trans->GetResponseInfo();
4865 ASSERT_TRUE(response);
4866 ASSERT_TRUE(response->headers);
4867 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4868
4869 // The following three tests assert that an authentication challenge was
4870 // received and that the stack is ready to respond to the challenge using
4871 // ambient credentials.
4872 EXPECT_EQ(401, response->headers->response_code());
4873 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584874 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164875
4876 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4877 EXPECT_THAT(callback.GetResult(rv), IsOk());
4878 response = trans->GetResponseInfo();
4879 ASSERT_TRUE(response);
4880 ASSERT_TRUE(response->headers);
4881
4882 // The following three tests assert that an authentication challenge was
4883 // received and that the stack needs explicit credentials before it is ready
4884 // to respond to the challenge.
4885 EXPECT_EQ(401, response->headers->response_code());
4886 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584887 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164888
4889 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4890 EXPECT_THAT(callback.GetResult(rv), IsOk());
4891 response = trans->GetResponseInfo();
4892 ASSERT_TRUE(response);
4893 ASSERT_TRUE(response->headers);
4894 EXPECT_EQ(200, response->headers->response_code());
4895
4896 trans.reset();
4897 session->CloseAllConnections();
4898}
4899
Matt Menked1eb6d42018-01-17 04:54:064900// Proxy resolver that returns a proxy with the same host and port for different
4901// schemes, based on the path of the URL being requests.
4902class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
4903 public:
4904 SameProxyWithDifferentSchemesProxyResolver() {}
4905 ~SameProxyWithDifferentSchemesProxyResolver() override {}
4906
4907 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
4908
4909 static HostPortPair ProxyHostPortPair() {
4910 return HostPortPair::FromString(ProxyHostPortPairAsString());
4911 }
4912
4913 // ProxyResolver implementation.
4914 int GetProxyForURL(const GURL& url,
4915 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:174916 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:064917 std::unique_ptr<Request>* request,
4918 const NetLogWithSource& /*net_log*/) override {
4919 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:574920 results->set_traffic_annotation(
4921 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:064922 if (url.path() == "/socks4") {
4923 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
4924 return OK;
4925 }
4926 if (url.path() == "/socks5") {
4927 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
4928 return OK;
4929 }
4930 if (url.path() == "/http") {
4931 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
4932 return OK;
4933 }
4934 if (url.path() == "/https") {
4935 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
4936 return OK;
4937 }
Matt Menkee8648fa2019-01-17 16:47:074938 if (url.path() == "/https_trusted") {
4939 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
4940 ProxyHostPortPair(),
4941 true /* is_trusted_proxy */));
4942 return OK;
4943 }
Matt Menked1eb6d42018-01-17 04:54:064944 NOTREACHED();
4945 return ERR_NOT_IMPLEMENTED;
4946 }
4947
4948 private:
4949 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
4950};
4951
4952class SameProxyWithDifferentSchemesProxyResolverFactory
4953 : public ProxyResolverFactory {
4954 public:
4955 SameProxyWithDifferentSchemesProxyResolverFactory()
4956 : ProxyResolverFactory(false) {}
4957
Lily Houghton99597862018-03-07 16:40:424958 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
4959 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:174960 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:424961 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:064962 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
4963 return OK;
4964 }
4965
4966 private:
4967 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
4968};
4969
4970// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:074971// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:064972// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
4973// request to foo.com using proxy.com as an HTTP proxy.
4974TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:494975 session_deps_.proxy_resolution_service =
4976 std::make_unique<ProxyResolutionService>(
4977 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
4978 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
4979 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
4980 nullptr);
Matt Menked1eb6d42018-01-17 04:54:064981
4982 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4983
4984 MockWrite socks_writes[] = {
4985 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
4986 kSOCKS4OkRequestLocalHostPort80Length),
4987 MockWrite(SYNCHRONOUS,
4988 "GET /socks4 HTTP/1.1\r\n"
4989 "Host: test\r\n"
4990 "Connection: keep-alive\r\n\r\n"),
4991 };
4992 MockRead socks_reads[] = {
4993 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
4994 MockRead("HTTP/1.0 200 OK\r\n"
4995 "Connection: keep-alive\r\n"
4996 "Content-Length: 15\r\n\r\n"
4997 "SOCKS4 Response"),
4998 };
Ryan Sleevib8d7ea02018-05-07 20:01:014999 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:065000 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
5001
5002 const char kSOCKS5Request[] = {
5003 0x05, // Version
5004 0x01, // Command (CONNECT)
5005 0x00, // Reserved
5006 0x03, // Address type (DOMAINNAME)
5007 0x04, // Length of domain (4)
5008 't', 'e', 's', 't', // Domain string
5009 0x00, 0x50, // 16-bit port (80)
5010 };
5011 MockWrite socks5_writes[] = {
5012 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245013 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065014 MockWrite(SYNCHRONOUS,
5015 "GET /socks5 HTTP/1.1\r\n"
5016 "Host: test\r\n"
5017 "Connection: keep-alive\r\n\r\n"),
5018 };
5019 MockRead socks5_reads[] = {
5020 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5021 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5022 MockRead("HTTP/1.0 200 OK\r\n"
5023 "Connection: keep-alive\r\n"
5024 "Content-Length: 15\r\n\r\n"
5025 "SOCKS5 Response"),
5026 };
Ryan Sleevib8d7ea02018-05-07 20:01:015027 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065028 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5029
5030 MockWrite http_writes[] = {
5031 MockWrite(SYNCHRONOUS,
5032 "GET http://test/http HTTP/1.1\r\n"
5033 "Host: test\r\n"
5034 "Proxy-Connection: keep-alive\r\n\r\n"),
5035 };
5036 MockRead http_reads[] = {
5037 MockRead("HTTP/1.1 200 OK\r\n"
5038 "Proxy-Connection: keep-alive\r\n"
5039 "Content-Length: 13\r\n\r\n"
5040 "HTTP Response"),
5041 };
Ryan Sleevib8d7ea02018-05-07 20:01:015042 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065043 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5044
5045 MockWrite https_writes[] = {
5046 MockWrite(SYNCHRONOUS,
5047 "GET http://test/https HTTP/1.1\r\n"
5048 "Host: test\r\n"
5049 "Proxy-Connection: keep-alive\r\n\r\n"),
5050 };
5051 MockRead https_reads[] = {
5052 MockRead("HTTP/1.1 200 OK\r\n"
5053 "Proxy-Connection: keep-alive\r\n"
5054 "Content-Length: 14\r\n\r\n"
5055 "HTTPS Response"),
5056 };
Ryan Sleevib8d7ea02018-05-07 20:01:015057 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065058 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5059 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5060 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5061
Matt Menkee8648fa2019-01-17 16:47:075062 MockWrite https_trusted_writes[] = {
5063 MockWrite(SYNCHRONOUS,
5064 "GET http://test/https_trusted HTTP/1.1\r\n"
5065 "Host: test\r\n"
5066 "Proxy-Connection: keep-alive\r\n\r\n"),
5067 };
5068 MockRead https_trusted_reads[] = {
5069 MockRead("HTTP/1.1 200 OK\r\n"
5070 "Proxy-Connection: keep-alive\r\n"
5071 "Content-Length: 22\r\n\r\n"
5072 "HTTPS Trusted Response"),
5073 };
5074 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5075 https_trusted_writes);
5076 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5077 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5078 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5079
Matt Menked1eb6d42018-01-17 04:54:065080 struct TestCase {
5081 GURL url;
5082 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075083 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065084 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075085 int expected_idle_socks4_sockets;
5086 int expected_idle_socks5_sockets;
5087 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5088 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065089 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075090 int expected_idle_https_sockets;
5091 // How many idle sockets there should be in the HTTPS proxy socket pool with
5092 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5093 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065094 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075095 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5096 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5097 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5098 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5099 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5100 1},
Matt Menked1eb6d42018-01-17 04:54:065101 };
5102
5103 for (const auto& test_case : kTestCases) {
5104 HttpRequestInfo request;
5105 request.method = "GET";
5106 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105107 request.traffic_annotation =
5108 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065109 std::unique_ptr<HttpNetworkTransaction> trans =
5110 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5111 session.get());
5112 TestCompletionCallback callback;
5113 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5114 EXPECT_THAT(callback.GetResult(rv), IsOk());
5115
5116 const HttpResponseInfo* response = trans->GetResponseInfo();
5117 ASSERT_TRUE(response);
5118 ASSERT_TRUE(response->headers);
5119 EXPECT_EQ(200, response->headers->response_code());
5120 std::string response_data;
5121 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5122 EXPECT_EQ(test_case.expected_response, response_data);
5123
5124 // Return the socket to the socket pool, so can make sure it's not used for
5125 // the next requests.
5126 trans.reset();
5127 base::RunLoop().RunUntilIdle();
5128
5129 // Check the number of idle sockets in the pool, to make sure that used
5130 // sockets are indeed being returned to the socket pool. If each request
5131 // doesn't return an idle socket to the pool, the test would incorrectly
5132 // pass.
Matt Menkee8648fa2019-01-17 16:47:075133 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5134 session
Matt Menked23ab952019-03-06 00:24:405135 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075136 HttpNetworkSession::NORMAL_SOCKET_POOL,
5137 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5138 SameProxyWithDifferentSchemesProxyResolver::
5139 ProxyHostPortPair()))
5140 ->IdleSocketCount());
5141 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5142 session
Matt Menked23ab952019-03-06 00:24:405143 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075144 HttpNetworkSession::NORMAL_SOCKET_POOL,
5145 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5146 SameProxyWithDifferentSchemesProxyResolver::
5147 ProxyHostPortPair()))
5148 ->IdleSocketCount());
5149 EXPECT_EQ(test_case.expected_idle_http_sockets,
5150 session
Matt Menked23ab952019-03-06 00:24:405151 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075152 HttpNetworkSession::NORMAL_SOCKET_POOL,
5153 ProxyServer(ProxyServer::SCHEME_HTTP,
5154 SameProxyWithDifferentSchemesProxyResolver::
5155 ProxyHostPortPair()))
5156 ->IdleSocketCount());
5157 EXPECT_EQ(test_case.expected_idle_https_sockets,
5158 session
Matt Menked23ab952019-03-06 00:24:405159 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075160 HttpNetworkSession::NORMAL_SOCKET_POOL,
5161 ProxyServer(ProxyServer::SCHEME_HTTPS,
5162 SameProxyWithDifferentSchemesProxyResolver::
5163 ProxyHostPortPair()))
5164 ->IdleSocketCount());
5165 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5166 session
Matt Menked23ab952019-03-06 00:24:405167 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075168 HttpNetworkSession::NORMAL_SOCKET_POOL,
5169 ProxyServer(ProxyServer::SCHEME_HTTPS,
5170 SameProxyWithDifferentSchemesProxyResolver::
5171 ProxyHostPortPair(),
5172 true /* is_trusted_proxy */))
5173 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065174 }
5175}
5176
[email protected]029c83b62013-01-24 05:28:205177// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015178TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205179 HttpRequestInfo request1;
5180 request1.method = "GET";
bncce36dca22015-04-21 22:11:235181 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105182 request1.traffic_annotation =
5183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205184
5185 HttpRequestInfo request2;
5186 request2.method = "GET";
bncce36dca22015-04-21 22:11:235187 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105188 request2.traffic_annotation =
5189 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205190
5191 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495192 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5193 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515194 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075195 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095196 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205197
5198 // Since we have proxy, should try to establish tunnel.
5199 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175200 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5201 "Host: www.example.org:443\r\n"
5202 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205203
rsleevidb16bb02015-11-12 23:47:175204 MockWrite("GET /1 HTTP/1.1\r\n"
5205 "Host: www.example.org\r\n"
5206 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205207
rsleevidb16bb02015-11-12 23:47:175208 MockWrite("GET /2 HTTP/1.1\r\n"
5209 "Host: www.example.org\r\n"
5210 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205211 };
5212
5213 // The proxy responds to the connect with a 407, using a persistent
5214 // connection.
5215 MockRead data_reads1[] = {
5216 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5217
5218 MockRead("HTTP/1.1 200 OK\r\n"),
5219 MockRead("Content-Length: 1\r\n\r\n"),
5220 MockRead(SYNCHRONOUS, "1"),
5221
5222 MockRead("HTTP/1.1 200 OK\r\n"),
5223 MockRead("Content-Length: 2\r\n\r\n"),
5224 MockRead(SYNCHRONOUS, "22"),
5225 };
5226
Ryan Sleevib8d7ea02018-05-07 20:01:015227 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075228 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205229 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075230 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205231
5232 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585233 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195234 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205235
5236 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015237 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205238
5239 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015240 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205241
5242 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525243 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475244 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525245 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205246 EXPECT_EQ(1, response1->headers->GetContentLength());
5247
5248 LoadTimingInfo load_timing_info1;
5249 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5250 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5251
5252 trans1.reset();
5253
5254 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585255 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195256 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205257
5258 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015259 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205260
5261 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015262 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205263
5264 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525265 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475266 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525267 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205268 EXPECT_EQ(2, response2->headers->GetContentLength());
5269
5270 LoadTimingInfo load_timing_info2;
5271 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5272 TestLoadTimingReused(load_timing_info2);
5273
5274 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5275
5276 trans2.reset();
5277 session->CloseAllConnections();
5278}
5279
5280// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015281TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205282 HttpRequestInfo request1;
5283 request1.method = "GET";
bncce36dca22015-04-21 22:11:235284 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105285 request1.traffic_annotation =
5286 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205287
5288 HttpRequestInfo request2;
5289 request2.method = "GET";
bncce36dca22015-04-21 22:11:235290 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105291 request2.traffic_annotation =
5292 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205293
5294 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595295 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495296 ProxyResolutionService::CreateFixedFromPacResult(
5297 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515298 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075299 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095300 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205301
5302 // Since we have proxy, should try to establish tunnel.
5303 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175304 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5305 "Host: www.example.org:443\r\n"
5306 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205307
rsleevidb16bb02015-11-12 23:47:175308 MockWrite("GET /1 HTTP/1.1\r\n"
5309 "Host: www.example.org\r\n"
5310 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205311
rsleevidb16bb02015-11-12 23:47:175312 MockWrite("GET /2 HTTP/1.1\r\n"
5313 "Host: www.example.org\r\n"
5314 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205315 };
5316
5317 // The proxy responds to the connect with a 407, using a persistent
5318 // connection.
5319 MockRead data_reads1[] = {
5320 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5321
5322 MockRead("HTTP/1.1 200 OK\r\n"),
5323 MockRead("Content-Length: 1\r\n\r\n"),
5324 MockRead(SYNCHRONOUS, "1"),
5325
5326 MockRead("HTTP/1.1 200 OK\r\n"),
5327 MockRead("Content-Length: 2\r\n\r\n"),
5328 MockRead(SYNCHRONOUS, "22"),
5329 };
5330
Ryan Sleevib8d7ea02018-05-07 20:01:015331 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075332 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205333 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075334 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205335
5336 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585337 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195338 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205339
5340 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015341 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205342
5343 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015344 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205345
5346 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525347 ASSERT_TRUE(response1);
5348 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205349 EXPECT_EQ(1, response1->headers->GetContentLength());
5350
5351 LoadTimingInfo load_timing_info1;
5352 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5353 TestLoadTimingNotReusedWithPac(load_timing_info1,
5354 CONNECT_TIMING_HAS_SSL_TIMES);
5355
5356 trans1.reset();
5357
5358 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585359 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195360 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205361
5362 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015363 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205364
5365 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015366 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205367
5368 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525369 ASSERT_TRUE(response2);
5370 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205371 EXPECT_EQ(2, response2->headers->GetContentLength());
5372
5373 LoadTimingInfo load_timing_info2;
5374 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5375 TestLoadTimingReusedWithPac(load_timing_info2);
5376
5377 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5378
5379 trans2.reset();
5380 session->CloseAllConnections();
5381}
5382
[email protected]2df19bb2010-08-25 20:13:465383// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015384TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275385 HttpRequestInfo request;
5386 request.method = "GET";
bncce36dca22015-04-21 22:11:235387 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105388 request.traffic_annotation =
5389 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275390
[email protected]2df19bb2010-08-25 20:13:465391 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495392 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5393 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515394 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075395 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095396 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:465397
[email protected]2df19bb2010-08-25 20:13:465398 // Since we have proxy, should use full url
5399 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235400 MockWrite(
5401 "GET http://www.example.org/ HTTP/1.1\r\n"
5402 "Host: www.example.org\r\n"
5403 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465404 };
5405
5406 MockRead data_reads1[] = {
5407 MockRead("HTTP/1.1 200 OK\r\n"),
5408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5409 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065410 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465411 };
5412
Ryan Sleevib8d7ea02018-05-07 20:01:015413 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075414 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065415 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075416 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465417
[email protected]49639fa2011-12-20 23:22:415418 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465419
bnc691fda62016-08-12 00:43:165420 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505421
bnc691fda62016-08-12 00:43:165422 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015423 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465424
5425 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015426 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465427
[email protected]58e32bb2013-01-21 18:23:255428 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165429 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255430 TestLoadTimingNotReused(load_timing_info,
5431 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5432
bnc691fda62016-08-12 00:43:165433 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525434 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465435
tbansal2ecbbc72016-10-06 17:15:475436 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:465437 EXPECT_TRUE(response->headers->IsKeepAlive());
5438 EXPECT_EQ(200, response->headers->response_code());
5439 EXPECT_EQ(100, response->headers->GetContentLength());
5440 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5441
5442 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585443 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:465444}
5445
[email protected]7642b5ae2010-09-01 20:55:175446// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015447TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275448 HttpRequestInfo request;
5449 request.method = "GET";
bncce36dca22015-04-21 22:11:235450 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105451 request.traffic_annotation =
5452 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275453
[email protected]7642b5ae2010-09-01 20:55:175454 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495455 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5456 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515457 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075458 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095459 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:175460
bncce36dca22015-04-21 22:11:235461 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135462 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455463 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415464 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:175465
Ryan Hamilton0239aac2018-05-19 00:03:135466 spdy::SpdySerializedFrame resp(
5467 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5468 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:175469 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415470 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:175471 };
5472
Ryan Sleevib8d7ea02018-05-07 20:01:015473 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075474 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:175475
[email protected]8ddf8322012-02-23 18:08:065476 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365477 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075478 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:175479
[email protected]49639fa2011-12-20 23:22:415480 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:175481
bnc691fda62016-08-12 00:43:165482 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505483
bnc691fda62016-08-12 00:43:165484 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015485 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:175486
5487 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015488 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:175489
[email protected]58e32bb2013-01-21 18:23:255490 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165491 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255492 TestLoadTimingNotReused(load_timing_info,
5493 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5494
bnc691fda62016-08-12 00:43:165495 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525496 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:475497 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:525498 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025499 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:175500
5501 std::string response_data;
bnc691fda62016-08-12 00:43:165502 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235503 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:175504}
5505
[email protected]1c173852014-06-19 12:51:505506// Verifies that a session which races and wins against the owning transaction
5507// (completing prior to host resolution), doesn't fail the transaction.
5508// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:015509TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:505510 HttpRequestInfo request;
5511 request.method = "GET";
bncce36dca22015-04-21 22:11:235512 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105513 request.traffic_annotation =
5514 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:505515
5516 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495517 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5518 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515519 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:505520 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095521 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:505522
bncce36dca22015-04-21 22:11:235523 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:135524 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455525 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415526 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:505527
Raul Tambre94493c652019-03-11 17:18:355528 spdy::SpdySerializedFrame resp(
5529 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135530 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:505531 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415532 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:505533 };
5534
Ryan Sleevib8d7ea02018-05-07 20:01:015535 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:505536 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5537
5538 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365539 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:505540 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5541
5542 TestCompletionCallback callback1;
5543
bnc691fda62016-08-12 00:43:165544 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:505545
5546 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:505547 session_deps_.host_resolver->set_ondemand_mode(true);
5548
bnc691fda62016-08-12 00:43:165549 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015550 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:505551
5552 // Race a session to the proxy, which completes first.
5553 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:045554 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115555 PRIVACY_MODE_DISABLED,
5556 SpdySessionKey::IsProxySession::kTrue, SocketTag());
[email protected]1c173852014-06-19 12:51:505557 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:525558 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:505559
5560 // Unstall the resolution begun by the transaction.
5561 session_deps_.host_resolver->set_ondemand_mode(true);
5562 session_deps_.host_resolver->ResolveAllPending();
5563
5564 EXPECT_FALSE(callback1.have_result());
5565 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015566 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:505567
bnc691fda62016-08-12 00:43:165568 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525569 ASSERT_TRUE(response);
5570 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025571 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:505572
5573 std::string response_data;
bnc691fda62016-08-12 00:43:165574 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:505575 EXPECT_EQ(kUploadData, response_data);
5576}
5577
[email protected]dc7bd1c52010-11-12 00:01:135578// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015579TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:275580 HttpRequestInfo request;
5581 request.method = "GET";
bncce36dca22015-04-21 22:11:235582 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105583 request.traffic_annotation =
5584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275585
[email protected]79cb5c12011-09-12 13:12:045586 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495587 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5588 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515589 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075590 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095591 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:135592
[email protected]dc7bd1c52010-11-12 00:01:135593 // The first request will be a bare GET, the second request will be a
5594 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:455595 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:135596 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485597 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385598 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:135599 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465600 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:135601 };
Ryan Hamilton0239aac2018-05-19 00:03:135602 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245603 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485604 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:135605 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415606 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:135607 };
5608
5609 // The first response is a 407 proxy authentication challenge, and the second
5610 // response will be a 200 response since the second request includes a valid
5611 // Authorization header.
5612 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465613 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:135614 };
Ryan Hamilton0239aac2018-05-19 00:03:135615 spdy::SpdySerializedFrame resp_authentication(
5616 spdy_util_.ConstructSpdyReplyError(
5617 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245618 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135619 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415620 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135621 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:355622 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135623 spdy::SpdySerializedFrame body_data(
5624 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:135625 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415626 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465627 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415628 CreateMockRead(resp_data, 4),
5629 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:135630 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:135631 };
5632
Ryan Sleevib8d7ea02018-05-07 20:01:015633 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075634 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:135635
[email protected]8ddf8322012-02-23 18:08:065636 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365637 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:135639
[email protected]49639fa2011-12-20 23:22:415640 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:135641
bnc691fda62016-08-12 00:43:165642 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:135643
bnc691fda62016-08-12 00:43:165644 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015645 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135646
5647 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015648 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135649
bnc691fda62016-08-12 00:43:165650 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135651
wezca1070932016-05-26 20:30:525652 ASSERT_TRUE(response);
5653 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:135654 EXPECT_EQ(407, response->headers->response_code());
5655 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585656 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:135657
[email protected]49639fa2011-12-20 23:22:415658 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:135659
bnc691fda62016-08-12 00:43:165660 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015661 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135662
5663 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015664 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135665
bnc691fda62016-08-12 00:43:165666 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135667
wezca1070932016-05-26 20:30:525668 ASSERT_TRUE(response_restart);
5669 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:135670 EXPECT_EQ(200, response_restart->headers->response_code());
5671 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585672 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:135673}
5674
[email protected]d9da5fe2010-10-13 22:37:165675// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:015676TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:275677 HttpRequestInfo request;
5678 request.method = "GET";
bncce36dca22015-04-21 22:11:235679 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105680 request.traffic_annotation =
5681 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275682
[email protected]d9da5fe2010-10-13 22:37:165683 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495684 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5685 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515686 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075687 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095688 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165689
bnc691fda62016-08-12 00:43:165690 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165691
bncce36dca22015-04-21 22:11:235692 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135693 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045694 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5695 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235696 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:165697
bncce36dca22015-04-21 22:11:235698 const char get[] =
5699 "GET / HTTP/1.1\r\n"
5700 "Host: www.example.org\r\n"
5701 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135702 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:195703 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:135704 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355705 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:165706 const char resp[] = "HTTP/1.1 200 OK\r\n"
5707 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135708 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:195709 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:135710 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:195711 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:135712 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:415713 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:045714
5715 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415716 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5717 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:045718 };
5719
[email protected]d9da5fe2010-10-13 22:37:165720 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415721 CreateMockRead(conn_resp, 1, ASYNC),
5722 CreateMockRead(wrapped_get_resp, 3, ASYNC),
5723 CreateMockRead(wrapped_body, 4, ASYNC),
5724 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135725 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:165726 };
5727
Ryan Sleevib8d7ea02018-05-07 20:01:015728 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075729 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165730
[email protected]8ddf8322012-02-23 18:08:065731 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365732 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065734 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075735 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165736
[email protected]49639fa2011-12-20 23:22:415737 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165738
bnc691fda62016-08-12 00:43:165739 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015740 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165741
5742 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015743 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165744
[email protected]58e32bb2013-01-21 18:23:255745 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165746 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255747 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5748
bnc691fda62016-08-12 00:43:165749 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525750 ASSERT_TRUE(response);
5751 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:165752 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5753
5754 std::string response_data;
bnc691fda62016-08-12 00:43:165755 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:165756 EXPECT_EQ("1234567890", response_data);
5757}
5758
5759// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:015760TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
5761 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:385762
[email protected]cb9bf6ca2011-01-28 13:15:275763 HttpRequestInfo request;
5764 request.method = "GET";
bncce36dca22015-04-21 22:11:235765 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105766 request.traffic_annotation =
5767 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275768
[email protected]d9da5fe2010-10-13 22:37:165769 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495770 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5771 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515772 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075773 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095774 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165775
bnc691fda62016-08-12 00:43:165776 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165777
bncce36dca22015-04-21 22:11:235778 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135779 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045780 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5781 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235782 // fetch https://www.example.org/ via SPDY
5783 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:135784 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:495785 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135786 spdy::SpdySerializedFrame wrapped_get(
5787 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
5788 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355789 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135790 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355791 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135792 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:025793 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135794 spdy::SpdySerializedFrame body(
5795 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
5796 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:025797 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135798 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:415799 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:135800 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:415801 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:045802
5803 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415804 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5805 CreateMockWrite(window_update_get_resp, 6),
5806 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:045807 };
5808
[email protected]d9da5fe2010-10-13 22:37:165809 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415810 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:095811 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:415812 CreateMockRead(wrapped_get_resp, 4, ASYNC),
5813 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135814 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:165815 };
5816
Ryan Sleevib8d7ea02018-05-07 20:01:015817 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075818 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165819
[email protected]8ddf8322012-02-23 18:08:065820 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365821 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075822 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065823 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365824 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075825 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165826
[email protected]49639fa2011-12-20 23:22:415827 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165828
bnc691fda62016-08-12 00:43:165829 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015830 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165831
rch32320842015-05-16 15:57:095832 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:555833 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:095834 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:595835 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:165836 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015837 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165838
[email protected]58e32bb2013-01-21 18:23:255839 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165840 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255841 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5842
bnc691fda62016-08-12 00:43:165843 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525844 ASSERT_TRUE(response);
5845 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025846 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:165847
5848 std::string response_data;
bnc691fda62016-08-12 00:43:165849 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235850 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:165851}
5852
5853// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015854TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:275855 HttpRequestInfo request;
5856 request.method = "GET";
bncce36dca22015-04-21 22:11:235857 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105858 request.traffic_annotation =
5859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275860
[email protected]d9da5fe2010-10-13 22:37:165861 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495862 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5863 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515864 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075865 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095866 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165867
bnc691fda62016-08-12 00:43:165868 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165869
bncce36dca22015-04-21 22:11:235870 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135871 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045872 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5873 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:135874 spdy::SpdySerializedFrame get(
5875 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:165876
5877 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415878 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:165879 };
5880
Ryan Hamilton0239aac2018-05-19 00:03:135881 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
5882 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:165883 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415884 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:165885 };
5886
Ryan Sleevib8d7ea02018-05-07 20:01:015887 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075888 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165889
[email protected]8ddf8322012-02-23 18:08:065890 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365891 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075892 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065893 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365894 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165896
[email protected]49639fa2011-12-20 23:22:415897 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165898
bnc691fda62016-08-12 00:43:165899 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015900 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165901
5902 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015903 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:165904
ttuttle960fcbf2016-04-19 13:26:325905 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:165906}
5907
Matt Menkecb2cd0982018-12-19 17:54:045908// Test the case where a proxied H2 session doesn't exist when an auth challenge
5909// is observed, but does exist by the time auth credentials are provided.
5910// Proxy-Connection: Close is used so that there's a second DNS lookup, which is
5911// what causes the existing H2 session to be noticed and reused.
5912TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
5913 ProxyConfig proxy_config;
5914 proxy_config.set_auto_detect(true);
5915 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
5916
5917 CapturingProxyResolver capturing_proxy_resolver;
5918 capturing_proxy_resolver.set_proxy_server(
5919 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
5920 session_deps_.proxy_resolution_service =
5921 std::make_unique<ProxyResolutionService>(
5922 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5923 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
5924 std::make_unique<CapturingProxyResolverFactory>(
5925 &capturing_proxy_resolver),
5926 nullptr);
5927
5928 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5929
5930 const char kMyUrl[] = "https://www.example.org/";
5931 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
5932 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355933 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:045934 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5935
5936 spdy_util_.UpdateWithStreamDestruction(1);
5937 spdy::SpdySerializedFrame get2(
5938 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
5939 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:355940 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:045941 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
5942
5943 MockWrite auth_challenge_writes[] = {
5944 MockWrite(ASYNC, 0,
5945 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5946 "Host: www.example.org:443\r\n"
5947 "Proxy-Connection: keep-alive\r\n\r\n"),
5948 };
5949
5950 MockRead auth_challenge_reads[] = {
5951 MockRead(ASYNC, 1,
5952 "HTTP/1.1 407 Authentication Required\r\n"
5953 "Content-Length: 0\r\n"
5954 "Proxy-Connection: close\r\n"
5955 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
5956 };
5957
5958 MockWrite spdy_writes[] = {
5959 MockWrite(ASYNC, 0,
5960 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5961 "Host: www.example.org:443\r\n"
5962 "Proxy-Connection: keep-alive\r\n"
5963 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5964 CreateMockWrite(get, 2),
5965 CreateMockWrite(get2, 5),
5966 };
5967
5968 MockRead spdy_reads[] = {
5969 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5970 CreateMockRead(get_resp, 3, ASYNC),
5971 CreateMockRead(body, 4, ASYNC),
5972 CreateMockRead(get_resp2, 6, ASYNC),
5973 CreateMockRead(body2, 7, ASYNC),
5974
5975 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
5976 };
5977
5978 SequencedSocketData auth_challenge1(auth_challenge_reads,
5979 auth_challenge_writes);
5980 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
5981
5982 SequencedSocketData auth_challenge2(auth_challenge_reads,
5983 auth_challenge_writes);
5984 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
5985
5986 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
5987 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5988
5989 SSLSocketDataProvider ssl(ASYNC, OK);
5990 ssl.next_proto = kProtoHTTP2;
5991 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5992
5993 TestCompletionCallback callback;
5994 std::string response_data;
5995
5996 // Run first request until an auth challenge is observed.
5997 HttpRequestInfo request1;
5998 request1.method = "GET";
5999 request1.url = GURL(kMyUrl);
6000 request1.traffic_annotation =
6001 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6002 HttpNetworkTransaction trans1(LOWEST, session.get());
6003 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6004 EXPECT_THAT(callback.GetResult(rv), IsOk());
6005 const HttpResponseInfo* response = trans1.GetResponseInfo();
6006 ASSERT_TRUE(response);
6007 ASSERT_TRUE(response->headers);
6008 EXPECT_EQ(407, response->headers->response_code());
6009 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586010 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046011
6012 // Run second request until an auth challenge is observed.
6013 HttpRequestInfo request2;
6014 request2.method = "GET";
6015 request2.url = GURL(kMyUrl);
6016 request2.traffic_annotation =
6017 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6018 HttpNetworkTransaction trans2(LOWEST, session.get());
6019 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6020 EXPECT_THAT(callback.GetResult(rv), IsOk());
6021 response = trans2.GetResponseInfo();
6022 ASSERT_TRUE(response);
6023 ASSERT_TRUE(response->headers);
6024 EXPECT_EQ(407, response->headers->response_code());
6025 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586026 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046027
6028 // Now provide credentials for the first request, and wait for it to complete.
6029 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6030 rv = callback.GetResult(rv);
6031 EXPECT_THAT(rv, IsOk());
6032 response = trans1.GetResponseInfo();
6033 ASSERT_TRUE(response);
6034 ASSERT_TRUE(response->headers);
6035 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6036 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6037 EXPECT_EQ(kUploadData, response_data);
6038
6039 // Now provide credentials for the second request. It should notice the
6040 // existing session, and reuse it.
6041 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6042 EXPECT_THAT(callback.GetResult(rv), IsOk());
6043 response = trans2.GetResponseInfo();
6044 ASSERT_TRUE(response);
6045 ASSERT_TRUE(response->headers);
6046 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6047 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6048 EXPECT_EQ(kUploadData, response_data);
6049}
6050
[email protected]f6c63db52013-02-02 00:35:226051// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6052// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016053TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226054 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6055 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496056 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6057 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516058 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076059 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096060 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506061 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226062
6063 HttpRequestInfo request1;
6064 request1.method = "GET";
bncce36dca22015-04-21 22:11:236065 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226066 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106067 request1.traffic_annotation =
6068 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226069
6070 HttpRequestInfo request2;
6071 request2.method = "GET";
bncce36dca22015-04-21 22:11:236072 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226073 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106074 request2.traffic_annotation =
6075 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226076
bncce36dca22015-04-21 22:11:236077 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136078 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046079 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6080 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136081 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356082 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226083
bncce36dca22015-04-21 22:11:236084 // Fetch https://www.example.org/ via HTTP.
6085 const char get1[] =
6086 "GET / HTTP/1.1\r\n"
6087 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226088 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136089 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196090 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226091 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6092 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136093 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196094 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136095 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196096 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136097 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416098 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226099
bncce36dca22015-04-21 22:11:236100 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136101 spdy::SpdyHeaderBlock connect2_block;
6102 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6103 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6104 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046105 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6106 false));
[email protected]601e03f12014-04-06 16:26:396107
Ryan Hamilton0239aac2018-05-19 00:03:136108 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356109 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226110
bncce36dca22015-04-21 22:11:236111 // Fetch https://mail.example.org/ via HTTP.
6112 const char get2[] =
6113 "GET / HTTP/1.1\r\n"
6114 "Host: mail.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_get2(
Bence Békyd74f4382018-02-20 18:26:196117 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226118 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6119 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136120 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196121 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136122 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196123 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226124
6125 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416126 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6127 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226128 };
6129
6130 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416131 CreateMockRead(conn_resp1, 1, ASYNC),
6132 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6133 CreateMockRead(wrapped_body1, 4, ASYNC),
6134 CreateMockRead(conn_resp2, 6, ASYNC),
6135 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6136 CreateMockRead(wrapped_body2, 9, ASYNC),
6137 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226138 };
6139
Ryan Sleevib8d7ea02018-05-07 20:01:016140 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506141 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226142
6143 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366144 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506145 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226146 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506147 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226148 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506149 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226150
6151 TestCompletionCallback callback;
6152
bnc691fda62016-08-12 00:43:166153 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206154 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016155 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226156
6157 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166158 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226159 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6160
bnc691fda62016-08-12 00:43:166161 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526162 ASSERT_TRUE(response);
6163 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226164 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6165
6166 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446167 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166168 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506169 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226170
bnc691fda62016-08-12 00:43:166171 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206172 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016173 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226174
6175 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166176 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226177 // Even though the SPDY connection is reused, a new tunnelled connection has
6178 // to be created, so the socket's load timing looks like a fresh connection.
6179 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6180
6181 // The requests should have different IDs, since they each are using their own
6182 // separate stream.
6183 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6184
bnc691fda62016-08-12 00:43:166185 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506186 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226187}
6188
6189// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6190// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016191TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226192 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6193 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496194 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6195 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516196 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076197 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096198 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506199 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226200
6201 HttpRequestInfo request1;
6202 request1.method = "GET";
bncce36dca22015-04-21 22:11:236203 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226204 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106205 request1.traffic_annotation =
6206 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226207
6208 HttpRequestInfo request2;
6209 request2.method = "GET";
bncce36dca22015-04-21 22:11:236210 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226211 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106212 request2.traffic_annotation =
6213 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226214
bncce36dca22015-04-21 22:11:236215 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136216 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046217 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6218 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136219 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356220 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226221
bncce36dca22015-04-21 22:11:236222 // Fetch https://www.example.org/ via HTTP.
6223 const char get1[] =
6224 "GET / HTTP/1.1\r\n"
6225 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226226 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136227 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196228 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226229 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6230 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136231 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196232 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136233 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196234 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136235 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416236 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226237
bncce36dca22015-04-21 22:11:236238 // Fetch https://www.example.org/2 via HTTP.
6239 const char get2[] =
6240 "GET /2 HTTP/1.1\r\n"
6241 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226242 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136243 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196244 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226245 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6246 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136247 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196248 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136249 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196250 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226251
6252 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416253 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6254 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226255 };
6256
6257 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416258 CreateMockRead(conn_resp1, 1, ASYNC),
6259 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466260 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416261 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466262 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416263 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226264 };
6265
Ryan Sleevib8d7ea02018-05-07 20:01:016266 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506267 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226268
6269 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366270 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506271 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226272 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506273 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226274
6275 TestCompletionCallback callback;
6276
bnc87dcefc2017-05-25 12:47:586277 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196278 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206279 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016280 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226281
6282 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016283 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226284
6285 LoadTimingInfo load_timing_info;
6286 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6287 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6288
6289 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526290 ASSERT_TRUE(response);
6291 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226292 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6293
6294 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446295 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506296 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226297 trans.reset();
6298
bnc87dcefc2017-05-25 12:47:586299 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196300 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206301 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016302 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226303
[email protected]f6c63db52013-02-02 00:35:226304 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016305 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226306
6307 LoadTimingInfo load_timing_info2;
6308 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6309 TestLoadTimingReused(load_timing_info2);
6310
6311 // The requests should have the same ID.
6312 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6313
[email protected]90499482013-06-01 00:39:506314 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226315}
6316
6317// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6318// Proxy to different servers.
bncd16676a2016-07-20 16:23:016319TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226320 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496321 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6322 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516323 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076324 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096325 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506326 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226327
6328 HttpRequestInfo request1;
6329 request1.method = "GET";
bncce36dca22015-04-21 22:11:236330 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226331 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106332 request1.traffic_annotation =
6333 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226334
6335 HttpRequestInfo request2;
6336 request2.method = "GET";
bncce36dca22015-04-21 22:11:236337 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226338 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106339 request2.traffic_annotation =
6340 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226341
bncce36dca22015-04-21 22:11:236342 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136343 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236344 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136345 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156346 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136347 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356348 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136349 spdy::SpdySerializedFrame body1(
6350 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386351 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226352
bncce36dca22015-04-21 22:11:236353 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136354 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236355 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136356 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156357 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136358 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356359 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136360 spdy::SpdySerializedFrame body2(
6361 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:226362
6363 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416364 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:226365 };
6366
6367 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416368 CreateMockRead(get_resp1, 1, ASYNC),
6369 CreateMockRead(body1, 2, ASYNC),
6370 CreateMockRead(get_resp2, 4, ASYNC),
6371 CreateMockRead(body2, 5, ASYNC),
6372 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:226373 };
6374
Ryan Sleevib8d7ea02018-05-07 20:01:016375 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506376 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226377
6378 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366379 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226381
6382 TestCompletionCallback callback;
6383
bnc87dcefc2017-05-25 12:47:586384 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196385 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206386 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016387 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226388
6389 LoadTimingInfo load_timing_info;
6390 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6391 TestLoadTimingNotReused(load_timing_info,
6392 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6393
6394 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526395 ASSERT_TRUE(response);
6396 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026397 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:226398
6399 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446400 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:506401 rv = trans->Read(buf.get(), 256, callback.callback());
6402 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226403 // Delete the first request, so the second one can reuse the socket.
6404 trans.reset();
6405
bnc691fda62016-08-12 00:43:166406 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206407 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016408 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226409
6410 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166411 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226412 TestLoadTimingReused(load_timing_info2);
6413
6414 // The requests should have the same ID.
6415 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6416
bnc691fda62016-08-12 00:43:166417 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506418 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226419}
6420
Matt Menke2436b2f2018-12-11 18:07:116421// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
6422// direct (non-proxied) request to the proxy server are not pooled, as that
6423// would break socket pool isolation.
6424TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
6425 ProxyConfig proxy_config;
6426 proxy_config.set_auto_detect(true);
6427 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6428
6429 CapturingProxyResolver capturing_proxy_resolver;
6430 session_deps_.proxy_resolution_service =
6431 std::make_unique<ProxyResolutionService>(
6432 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6433 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6434 std::make_unique<CapturingProxyResolverFactory>(
6435 &capturing_proxy_resolver),
6436 nullptr);
6437
6438 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6439
6440 SpdyTestUtil spdy_util1;
6441 // CONNECT to www.example.org:443 via HTTP/2.
6442 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046443 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6444 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116445 // fetch https://www.example.org/ via HTTP/2.
6446 const char kMyUrl[] = "https://www.example.org/";
6447 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6448 spdy::SpdySerializedFrame wrapped_get(
6449 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6450 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356451 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116452 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356453 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116454 spdy::SpdySerializedFrame wrapped_get_resp(
6455 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6456 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
6457 spdy::SpdySerializedFrame wrapped_body(
6458 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6459 spdy::SpdySerializedFrame window_update_get_resp(
6460 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6461 spdy::SpdySerializedFrame window_update_body(
6462 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6463
6464 MockWrite spdy_writes1[] = {
6465 CreateMockWrite(connect, 0),
6466 CreateMockWrite(wrapped_get, 2),
6467 CreateMockWrite(window_update_get_resp, 6),
6468 CreateMockWrite(window_update_body, 7),
6469 };
6470
6471 MockRead spdy_reads1[] = {
6472 CreateMockRead(conn_resp, 1, ASYNC),
6473 MockRead(ASYNC, ERR_IO_PENDING, 3),
6474 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6475 CreateMockRead(wrapped_body, 5, ASYNC),
6476 MockRead(ASYNC, 0, 8),
6477 };
6478
6479 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6480 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6481
6482 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
6483 // a new pipe.
6484 SpdyTestUtil spdy_util2;
6485 spdy::SpdySerializedFrame req(
6486 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6487 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
6488
6489 spdy::SpdySerializedFrame resp(
6490 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6491 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
6492 MockRead spdy_reads2[] = {
6493 CreateMockRead(resp, 1),
6494 CreateMockRead(data, 2),
6495 MockRead(ASYNC, 0, 3),
6496 };
6497 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6498 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6499
6500 SSLSocketDataProvider ssl(ASYNC, OK);
6501 ssl.next_proto = kProtoHTTP2;
6502 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6503 SSLSocketDataProvider ssl2(ASYNC, OK);
6504 ssl2.next_proto = kProtoHTTP2;
6505 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6506 SSLSocketDataProvider ssl3(ASYNC, OK);
6507 ssl3.next_proto = kProtoHTTP2;
6508 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6509
6510 TestCompletionCallback callback;
6511 std::string response_data;
6512
6513 // Make a request using proxy:70 as a HTTP/2 proxy.
6514 capturing_proxy_resolver.set_proxy_server(
6515 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6516 HttpRequestInfo request1;
6517 request1.method = "GET";
6518 request1.url = GURL("https://www.example.org/");
6519 request1.traffic_annotation =
6520 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6521
6522 HttpNetworkTransaction trans1(LOWEST, session.get());
6523 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6524 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6525
6526 // Allow the SpdyProxyClientSocket's write callback to complete.
6527 base::RunLoop().RunUntilIdle();
6528 // Now allow the read of the response to complete.
6529 spdy_data1.Resume();
6530 rv = callback.WaitForResult();
6531 EXPECT_THAT(rv, IsOk());
6532
6533 const HttpResponseInfo* response = trans1.GetResponseInfo();
6534 ASSERT_TRUE(response);
6535 ASSERT_TRUE(response->headers);
6536 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6537
6538 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6539 EXPECT_EQ(kUploadData, response_data);
6540 RunUntilIdle();
6541
6542 // Make a direct HTTP/2 request to proxy:70.
6543 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6544 HttpRequestInfo request2;
6545 request2.method = "GET";
6546 request2.url = GURL("https://proxy:70/");
6547 request2.traffic_annotation =
6548 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6549 HttpNetworkTransaction trans2(LOWEST, session.get());
6550 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
6551 NetLogWithSource())),
6552 IsOk());
6553 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6554}
6555
6556// Same as above, but reverse request order, since the code to check for an
6557// existing session is different for tunnels and direct connections.
6558TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
6559 // Configure against https proxy server "myproxy:80".
6560 ProxyConfig proxy_config;
6561 proxy_config.set_auto_detect(true);
6562 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6563
6564 CapturingProxyResolver capturing_proxy_resolver;
6565 session_deps_.proxy_resolution_service =
6566 std::make_unique<ProxyResolutionService>(
6567 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6568 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6569 std::make_unique<CapturingProxyResolverFactory>(
6570 &capturing_proxy_resolver),
6571 nullptr);
6572
6573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6574 // Fetch https://proxy:70/ via HTTP/2.
6575 SpdyTestUtil spdy_util1;
6576 spdy::SpdySerializedFrame req(
6577 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6578 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
6579
6580 spdy::SpdySerializedFrame resp(
6581 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
6582 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
6583 MockRead spdy_reads1[] = {
6584 CreateMockRead(resp, 1),
6585 CreateMockRead(data, 2),
6586 MockRead(ASYNC, 0, 3),
6587 };
6588 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6589 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6590
6591 SpdyTestUtil spdy_util2;
6592 // CONNECT to www.example.org:443 via HTTP/2.
6593 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046594 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6595 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116596 // fetch https://www.example.org/ via HTTP/2.
6597 const char kMyUrl[] = "https://www.example.org/";
6598 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6599 spdy::SpdySerializedFrame wrapped_get(
6600 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6601 spdy::SpdySerializedFrame conn_resp(
6602 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6603 spdy::SpdySerializedFrame get_resp(
6604 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6605 spdy::SpdySerializedFrame wrapped_get_resp(
6606 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6607 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
6608 spdy::SpdySerializedFrame wrapped_body(
6609 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6610 spdy::SpdySerializedFrame window_update_get_resp(
6611 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6612 spdy::SpdySerializedFrame window_update_body(
6613 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6614
6615 MockWrite spdy_writes2[] = {
6616 CreateMockWrite(connect, 0),
6617 CreateMockWrite(wrapped_get, 2),
6618 CreateMockWrite(window_update_get_resp, 6),
6619 CreateMockWrite(window_update_body, 7),
6620 };
6621
6622 MockRead spdy_reads2[] = {
6623 CreateMockRead(conn_resp, 1, ASYNC),
6624 MockRead(ASYNC, ERR_IO_PENDING, 3),
6625 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6626 CreateMockRead(wrapped_body, 5, ASYNC),
6627 MockRead(ASYNC, 0, 8),
6628 };
6629
6630 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6631 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6632
6633 SSLSocketDataProvider ssl(ASYNC, OK);
6634 ssl.next_proto = kProtoHTTP2;
6635 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6636 SSLSocketDataProvider ssl2(ASYNC, OK);
6637 ssl2.next_proto = kProtoHTTP2;
6638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6639 SSLSocketDataProvider ssl3(ASYNC, OK);
6640 ssl3.next_proto = kProtoHTTP2;
6641 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6642
6643 TestCompletionCallback callback;
6644 std::string response_data;
6645
6646 // Make a direct HTTP/2 request to proxy:70.
6647 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6648 HttpRequestInfo request1;
6649 request1.method = "GET";
6650 request1.url = GURL("https://proxy:70/");
6651 request1.traffic_annotation =
6652 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6653 HttpNetworkTransaction trans1(LOWEST, session.get());
6654 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
6655 NetLogWithSource())),
6656 IsOk());
6657 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6658 RunUntilIdle();
6659
6660 // Make a request using proxy:70 as a HTTP/2 proxy.
6661 capturing_proxy_resolver.set_proxy_server(
6662 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6663 HttpRequestInfo request2;
6664 request2.method = "GET";
6665 request2.url = GURL("https://www.example.org/");
6666 request2.traffic_annotation =
6667 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6668
6669 HttpNetworkTransaction trans2(LOWEST, session.get());
6670 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6672
6673 // Allow the SpdyProxyClientSocket's write callback to complete.
6674 base::RunLoop().RunUntilIdle();
6675 // Now allow the read of the response to complete.
6676 spdy_data2.Resume();
6677 rv = callback.WaitForResult();
6678 EXPECT_THAT(rv, IsOk());
6679
6680 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
6681 ASSERT_TRUE(response2);
6682 ASSERT_TRUE(response2->headers);
6683 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
6684
6685 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6686 EXPECT_EQ(kUploadData, response_data);
6687}
6688
[email protected]2df19bb2010-08-25 20:13:466689// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:016690TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:466691 HttpRequestInfo request;
6692 request.method = "GET";
bncce36dca22015-04-21 22:11:236693 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:466694 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:296695 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:106696 request.traffic_annotation =
6697 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:466698
[email protected]79cb5c12011-09-12 13:12:046699 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496700 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6701 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516702 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076703 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096704 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276705
[email protected]2df19bb2010-08-25 20:13:466706 // Since we have proxy, should use full url
6707 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:166708 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6709 "Host: www.example.org\r\n"
6710 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466711
bnc691fda62016-08-12 00:43:166712 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:236713 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:166714 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6715 "Host: www.example.org\r\n"
6716 "Proxy-Connection: keep-alive\r\n"
6717 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466718 };
6719
6720 // The proxy responds to the GET with a 407, using a persistent
6721 // connection.
6722 MockRead data_reads1[] = {
6723 // No credentials.
6724 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6725 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6726 MockRead("Proxy-Connection: keep-alive\r\n"),
6727 MockRead("Content-Length: 0\r\n\r\n"),
6728
6729 MockRead("HTTP/1.1 200 OK\r\n"),
6730 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6731 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066732 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466733 };
6734
Ryan Sleevib8d7ea02018-05-07 20:01:016735 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076736 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066737 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466739
[email protected]49639fa2011-12-20 23:22:416740 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466741
bnc691fda62016-08-12 00:43:166742 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506743
bnc691fda62016-08-12 00:43:166744 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016745 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466746
6747 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016748 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466749
[email protected]58e32bb2013-01-21 18:23:256750 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166751 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256752 TestLoadTimingNotReused(load_timing_info,
6753 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6754
bnc691fda62016-08-12 00:43:166755 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526756 ASSERT_TRUE(response);
6757 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:466758 EXPECT_EQ(407, response->headers->response_code());
6759 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586760 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:506761 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466762
[email protected]49639fa2011-12-20 23:22:416763 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:466764
bnc691fda62016-08-12 00:43:166765 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016766 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466767
6768 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016769 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466770
[email protected]58e32bb2013-01-21 18:23:256771 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:166772 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256773 // Retrying with HTTP AUTH is considered to be reusing a socket.
6774 TestLoadTimingReused(load_timing_info);
6775
bnc691fda62016-08-12 00:43:166776 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526777 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466778
6779 EXPECT_TRUE(response->headers->IsKeepAlive());
6780 EXPECT_EQ(200, response->headers->response_code());
6781 EXPECT_EQ(100, response->headers->GetContentLength());
6782 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:506783 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466784
6785 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586786 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466787}
6788
[email protected]23e482282013-06-14 16:08:026789void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:086790 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:426791 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:086792 request.method = "GET";
bncce36dca22015-04-21 22:11:236793 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106794 request.traffic_annotation =
6795 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:086796
[email protected]cb9bf6ca2011-01-28 13:15:276797 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496798 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6799 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096800 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276801
[email protected]c744cf22009-02-27 07:28:086802 // Since we have proxy, should try to establish tunnel.
6803 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:176804 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6805 "Host: www.example.org:443\r\n"
6806 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:086807 };
6808
6809 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:236810 status, MockRead("Content-Length: 10\r\n\r\n"),
6811 // No response body because the test stops reading here.
6812 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:086813 };
6814
Ryan Sleevib8d7ea02018-05-07 20:01:016815 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:076816 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:086817
[email protected]49639fa2011-12-20 23:22:416818 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:086819
bnc691fda62016-08-12 00:43:166820 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506821
tfarina42834112016-09-22 13:38:206822 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016823 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:086824
6825 rv = callback.WaitForResult();
6826 EXPECT_EQ(expected_status, rv);
6827}
6828
[email protected]23e482282013-06-14 16:08:026829void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:236830 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:086831 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:426832 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:086833}
6834
bncd16676a2016-07-20 16:23:016835TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:086836 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
6837}
6838
bncd16676a2016-07-20 16:23:016839TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:086840 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
6841}
6842
bncd16676a2016-07-20 16:23:016843TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:086844 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
6845}
6846
bncd16676a2016-07-20 16:23:016847TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:086848 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
6849}
6850
bncd16676a2016-07-20 16:23:016851TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:086852 ConnectStatusHelper(
6853 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
6854}
6855
bncd16676a2016-07-20 16:23:016856TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:086857 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
6858}
6859
bncd16676a2016-07-20 16:23:016860TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:086861 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
6862}
6863
bncd16676a2016-07-20 16:23:016864TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:086865 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
6866}
6867
bncd16676a2016-07-20 16:23:016868TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:086869 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
6870}
6871
bncd16676a2016-07-20 16:23:016872TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:086873 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
6874}
6875
bncd16676a2016-07-20 16:23:016876TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:086877 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
6878}
6879
bncd16676a2016-07-20 16:23:016880TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:086881 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
6882}
6883
bncd16676a2016-07-20 16:23:016884TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:086885 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
6886}
6887
bncd16676a2016-07-20 16:23:016888TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:086889 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
6890}
6891
bncd16676a2016-07-20 16:23:016892TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:086893 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
6894}
6895
bncd16676a2016-07-20 16:23:016896TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:086897 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
6898}
6899
bncd16676a2016-07-20 16:23:016900TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:376901 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
6902}
6903
bncd16676a2016-07-20 16:23:016904TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:086905 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
6906}
6907
bncd16676a2016-07-20 16:23:016908TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:086909 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
6910}
6911
bncd16676a2016-07-20 16:23:016912TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:086913 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
6914}
6915
bncd16676a2016-07-20 16:23:016916TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:086917 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
6918}
6919
bncd16676a2016-07-20 16:23:016920TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:086921 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
6922}
6923
bncd16676a2016-07-20 16:23:016924TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:086925 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
6926}
6927
bncd16676a2016-07-20 16:23:016928TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:086929 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
6930}
6931
bncd16676a2016-07-20 16:23:016932TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:086933 ConnectStatusHelperWithExpectedStatus(
6934 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:546935 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:086936}
6937
bncd16676a2016-07-20 16:23:016938TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:086939 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
6940}
6941
bncd16676a2016-07-20 16:23:016942TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:086943 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
6944}
6945
bncd16676a2016-07-20 16:23:016946TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:086947 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
6948}
6949
bncd16676a2016-07-20 16:23:016950TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:086951 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
6952}
6953
bncd16676a2016-07-20 16:23:016954TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:086955 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
6956}
6957
bncd16676a2016-07-20 16:23:016958TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:086959 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
6960}
6961
bncd16676a2016-07-20 16:23:016962TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:086963 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
6964}
6965
bncd16676a2016-07-20 16:23:016966TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:086967 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
6968}
6969
bncd16676a2016-07-20 16:23:016970TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:086971 ConnectStatusHelper(
6972 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
6973}
6974
bncd16676a2016-07-20 16:23:016975TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:086976 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
6977}
6978
bncd16676a2016-07-20 16:23:016979TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:086980 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
6981}
6982
bncd16676a2016-07-20 16:23:016983TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:086984 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
6985}
6986
bncd16676a2016-07-20 16:23:016987TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:086988 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
6989}
6990
bncd16676a2016-07-20 16:23:016991TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:086992 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
6993}
6994
bncd16676a2016-07-20 16:23:016995TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:086996 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
6997}
6998
bncd16676a2016-07-20 16:23:016999TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087000 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7001}
7002
[email protected]038e9a32008-10-08 22:40:167003// Test the flow when both the proxy server AND origin server require
7004// authentication. Again, this uses basic auth for both since that is
7005// the simplest to mock.
bncd16676a2016-07-20 16:23:017006TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277007 HttpRequestInfo request;
7008 request.method = "GET";
bncce36dca22015-04-21 22:11:237009 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107010 request.traffic_annotation =
7011 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277012
[email protected]038e9a32008-10-08 22:40:167013 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497014 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7015 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097016 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077017
bnc691fda62016-08-12 00:43:167018 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167019
[email protected]f9ee6b52008-11-08 06:46:237020 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237021 MockWrite(
7022 "GET http://www.example.org/ HTTP/1.1\r\n"
7023 "Host: www.example.org\r\n"
7024 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237025 };
7026
[email protected]038e9a32008-10-08 22:40:167027 MockRead data_reads1[] = {
7028 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7029 // Give a couple authenticate options (only the middle one is actually
7030 // supported).
[email protected]22927ad2009-09-21 19:56:197031 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167032 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7033 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7034 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7035 // Large content-length -- won't matter, as connection will be reset.
7036 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067037 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167038 };
7039
bnc691fda62016-08-12 00:43:167040 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167041 // request we should be issuing -- the final header line contains the
7042 // proxy's credentials.
7043 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237044 MockWrite(
7045 "GET http://www.example.org/ HTTP/1.1\r\n"
7046 "Host: www.example.org\r\n"
7047 "Proxy-Connection: keep-alive\r\n"
7048 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167049 };
7050
7051 // Now the proxy server lets the request pass through to origin server.
7052 // The origin server responds with a 401.
7053 MockRead data_reads2[] = {
7054 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7055 // Note: We are using the same realm-name as the proxy server. This is
7056 // completely valid, as realms are unique across hosts.
7057 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7058 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7059 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067060 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167061 };
7062
bnc691fda62016-08-12 00:43:167063 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167064 // the credentials for both the proxy and origin server.
7065 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237066 MockWrite(
7067 "GET http://www.example.org/ HTTP/1.1\r\n"
7068 "Host: www.example.org\r\n"
7069 "Proxy-Connection: keep-alive\r\n"
7070 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7071 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167072 };
7073
7074 // Lastly we get the desired content.
7075 MockRead data_reads3[] = {
7076 MockRead("HTTP/1.0 200 OK\r\n"),
7077 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7078 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067079 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167080 };
7081
Ryan Sleevib8d7ea02018-05-07 20:01:017082 StaticSocketDataProvider data1(data_reads1, data_writes1);
7083 StaticSocketDataProvider data2(data_reads2, data_writes2);
7084 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077085 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7086 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7087 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167088
[email protected]49639fa2011-12-20 23:22:417089 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167090
tfarina42834112016-09-22 13:38:207091 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017092 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167093
7094 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017095 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167096
bnc691fda62016-08-12 00:43:167097 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527098 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587099 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167100
[email protected]49639fa2011-12-20 23:22:417101 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167102
bnc691fda62016-08-12 00:43:167103 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017104 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167105
7106 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017107 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167108
bnc691fda62016-08-12 00:43:167109 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527110 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587111 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167112
[email protected]49639fa2011-12-20 23:22:417113 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167114
bnc691fda62016-08-12 00:43:167115 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7116 callback3.callback());
robpercival214763f2016-07-01 23:27:017117 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167118
7119 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017120 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167121
bnc691fda62016-08-12 00:43:167122 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587123 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167124 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167125}
[email protected]4ddaf2502008-10-23 18:26:197126
[email protected]ea9dc9a2009-09-05 00:43:327127// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7128// can't hook into its internals to cause it to generate predictable NTLM
7129// authorization headers.
7130#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377131// The NTLM authentication unit tests are based on known test data from the
7132// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7133// flow rather than the implementation of the NTLM protocol. See net/ntlm
7134// for the implementation and testing of the protocol.
7135//
7136// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297137
7138// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557139TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427140 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247141 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557142 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107143 request.traffic_annotation =
7144 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547145
7146 // Ensure load is not disrupted by flags which suppress behaviour specific
7147 // to other auth schemes.
7148 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247149
Zentaro Kavanagh6ccee512017-09-28 18:34:097150 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7151 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097152 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277153
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377154 // Generate the NTLM messages based on known test data.
7155 std::string negotiate_msg;
7156 std::string challenge_msg;
7157 std::string authenticate_msg;
7158 base::Base64Encode(
7159 base::StringPiece(
7160 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247161 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377162 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557163 base::Base64Encode(
7164 base::StringPiece(
7165 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247166 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557167 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377168 base::Base64Encode(
7169 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097170 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557171 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247172 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557173 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377174 &authenticate_msg);
7175
[email protected]3f918782009-02-28 01:29:247176 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557177 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7178 "Host: server\r\n"
7179 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247180 };
7181
7182 MockRead data_reads1[] = {
7183 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047184 // Negotiate and NTLM are often requested together. However, we only want
7185 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7186 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247187 MockRead("WWW-Authenticate: NTLM\r\n"),
7188 MockRead("Connection: close\r\n"),
7189 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367190 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247191 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247192 };
7193
7194 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167195 // After restarting with a null identity, this is the
7196 // request we should be issuing -- the final header line contains a Type
7197 // 1 message.
7198 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557199 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167200 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377201 "Authorization: NTLM "),
7202 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247203
bnc691fda62016-08-12 00:43:167204 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377205 // (using correct credentials). The second request continues on the
7206 // same connection.
bnc691fda62016-08-12 00:43:167207 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557208 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167209 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377210 "Authorization: NTLM "),
7211 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247212 };
7213
7214 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027215 // The origin server responds with a Type 2 message.
7216 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377217 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7218 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027219 MockRead("Content-Type: text/html\r\n\r\n"),
7220 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247221
Bence Béky1e4ef192017-09-18 19:58:027222 // Lastly we get the desired content.
7223 MockRead("HTTP/1.1 200 OK\r\n"),
7224 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7225 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247226 };
7227
Ryan Sleevib8d7ea02018-05-07 20:01:017228 StaticSocketDataProvider data1(data_reads1, data_writes1);
7229 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077230 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7231 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247232
Bence Béky83eb3512017-09-05 12:56:097233 SSLSocketDataProvider ssl1(ASYNC, OK);
7234 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7235 SSLSocketDataProvider ssl2(ASYNC, OK);
7236 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7237
[email protected]49639fa2011-12-20 23:22:417238 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247239
bnc691fda62016-08-12 00:43:167240 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507241
tfarina42834112016-09-22 13:38:207242 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017243 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247244
7245 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017246 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247247
bnc691fda62016-08-12 00:43:167248 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227249
bnc691fda62016-08-12 00:43:167250 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527251 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587252 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247253
[email protected]49639fa2011-12-20 23:22:417254 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257255
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377256 rv = trans.RestartWithAuth(
7257 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7258 callback2.callback());
robpercival214763f2016-07-01 23:27:017259 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257260
7261 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017262 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257263
bnc691fda62016-08-12 00:43:167264 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257265
bnc691fda62016-08-12 00:43:167266 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527267 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587268 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257269
[email protected]49639fa2011-12-20 23:22:417270 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247271
bnc691fda62016-08-12 00:43:167272 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017273 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247274
[email protected]0757e7702009-03-27 04:00:227275 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017276 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247277
bnc691fda62016-08-12 00:43:167278 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527279 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587280 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027281 EXPECT_EQ(14, response->headers->GetContentLength());
7282
7283 std::string response_data;
7284 rv = ReadTransaction(&trans, &response_data);
7285 EXPECT_THAT(rv, IsOk());
7286 EXPECT_EQ("Please Login\r\n", response_data);
7287
7288 EXPECT_TRUE(data1.AllReadDataConsumed());
7289 EXPECT_TRUE(data1.AllWriteDataConsumed());
7290 EXPECT_TRUE(data2.AllReadDataConsumed());
7291 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247292}
7293
[email protected]385a4672009-03-11 22:21:297294// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557295TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427296 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297297 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557298 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107299 request.traffic_annotation =
7300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297301
Zentaro Kavanagh6ccee512017-09-28 18:34:097302 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7303 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277305
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377306 // Generate the NTLM messages based on known test data.
7307 std::string negotiate_msg;
7308 std::string challenge_msg;
7309 std::string authenticate_msg;
7310 base::Base64Encode(
7311 base::StringPiece(
7312 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247313 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377314 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557315 base::Base64Encode(
7316 base::StringPiece(
7317 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247318 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557319 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377320 base::Base64Encode(
7321 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097322 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557323 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247324 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557325 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377326 &authenticate_msg);
7327
7328 // The authenticate message when |kWrongPassword| is sent.
7329 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557330 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7331 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7332 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7333 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7334 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7335 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377336
Zentaro Kavanagh1890a3d2018-01-29 19:52:557337 // Sanity check that it's the same length as the correct authenticate message
7338 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377339 ASSERT_EQ(authenticate_msg.length(),
7340 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557341 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377342
[email protected]385a4672009-03-11 22:21:297343 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557344 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7345 "Host: server\r\n"
7346 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297347 };
7348
7349 MockRead data_reads1[] = {
7350 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047351 // Negotiate and NTLM are often requested together. However, we only want
7352 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7353 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297354 MockRead("WWW-Authenticate: NTLM\r\n"),
7355 MockRead("Connection: close\r\n"),
7356 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367357 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297358 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297359 };
7360
7361 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167362 // After restarting with a null identity, this is the
7363 // request we should be issuing -- the final header line contains a Type
7364 // 1 message.
7365 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557366 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167367 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377368 "Authorization: NTLM "),
7369 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297370
bnc691fda62016-08-12 00:43:167371 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377372 // (using incorrect credentials). The second request continues on the
7373 // same connection.
bnc691fda62016-08-12 00:43:167374 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557375 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167376 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377377 "Authorization: NTLM "),
7378 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297379 };
7380
7381 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377382 // The origin server responds with a Type 2 message.
7383 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7384 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7385 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
7386 MockRead("Content-Type: text/html\r\n\r\n"),
7387 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297388
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377389 // Wrong password.
7390 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7391 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
7392 MockRead("Content-Length: 42\r\n"),
7393 MockRead("Content-Type: text/html\r\n\r\n"),
7394 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297395 };
7396
7397 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:167398 // After restarting with a null identity, this is the
7399 // request we should be issuing -- the final header line contains a Type
7400 // 1 message.
7401 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(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297406
bnc691fda62016-08-12 00:43:167407 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7408 // (the credentials for the origin server). The second request continues
7409 // on the same connection.
7410 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557411 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167412 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377413 "Authorization: NTLM "),
7414 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297415 };
7416
7417 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:027418 // The origin server responds with a Type 2 message.
7419 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377420 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7421 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027422 MockRead("Content-Type: text/html\r\n\r\n"),
7423 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297424
Bence Béky1e4ef192017-09-18 19:58:027425 // Lastly we get the desired content.
7426 MockRead("HTTP/1.1 200 OK\r\n"),
7427 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7428 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:297429 };
7430
Ryan Sleevib8d7ea02018-05-07 20:01:017431 StaticSocketDataProvider data1(data_reads1, data_writes1);
7432 StaticSocketDataProvider data2(data_reads2, data_writes2);
7433 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077434 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7435 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7436 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:297437
Bence Béky83eb3512017-09-05 12:56:097438 SSLSocketDataProvider ssl1(ASYNC, OK);
7439 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7440 SSLSocketDataProvider ssl2(ASYNC, OK);
7441 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7442 SSLSocketDataProvider ssl3(ASYNC, OK);
7443 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7444
[email protected]49639fa2011-12-20 23:22:417445 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:297446
bnc691fda62016-08-12 00:43:167447 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507448
tfarina42834112016-09-22 13:38:207449 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017450 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297451
7452 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017453 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297454
bnc691fda62016-08-12 00:43:167455 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:297456
bnc691fda62016-08-12 00:43:167457 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527458 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587459 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:297460
[email protected]49639fa2011-12-20 23:22:417461 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:297462
[email protected]0757e7702009-03-27 04:00:227463 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377464 rv = trans.RestartWithAuth(
7465 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
7466 callback2.callback());
robpercival214763f2016-07-01 23:27:017467 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297468
[email protected]10af5fe72011-01-31 16:17:257469 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017470 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297471
bnc691fda62016-08-12 00:43:167472 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417473 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:167474 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017475 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257476 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017477 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:167478 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227479
bnc691fda62016-08-12 00:43:167480 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527481 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587482 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:227483
[email protected]49639fa2011-12-20 23:22:417484 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:227485
7486 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377487 rv = trans.RestartWithAuth(
7488 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7489 callback4.callback());
robpercival214763f2016-07-01 23:27:017490 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257491
7492 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:017493 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257494
bnc691fda62016-08-12 00:43:167495 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257496
[email protected]49639fa2011-12-20 23:22:417497 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:257498
7499 // One more roundtrip
bnc691fda62016-08-12 00:43:167500 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:017501 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227502
7503 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:017504 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227505
bnc691fda62016-08-12 00:43:167506 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587507 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027508 EXPECT_EQ(14, response->headers->GetContentLength());
7509
7510 std::string response_data;
7511 rv = ReadTransaction(&trans, &response_data);
7512 EXPECT_THAT(rv, IsOk());
7513 EXPECT_EQ("Please Login\r\n", response_data);
7514
7515 EXPECT_TRUE(data1.AllReadDataConsumed());
7516 EXPECT_TRUE(data1.AllWriteDataConsumed());
7517 EXPECT_TRUE(data2.AllReadDataConsumed());
7518 EXPECT_TRUE(data2.AllWriteDataConsumed());
7519 EXPECT_TRUE(data3.AllReadDataConsumed());
7520 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:297521}
Bence Béky83eb3512017-09-05 12:56:097522
Bence Béky3238f2e12017-09-22 22:44:497523// Server requests NTLM authentication, which is not supported over HTTP/2.
7524// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:097525TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:097526 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7527 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:097528
Zentaro Kavanagh1890a3d2018-01-29 19:52:557529 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:097530
7531 HttpRequestInfo request;
7532 request.method = "GET";
7533 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:107534 request.traffic_annotation =
7535 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:097536
7537 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:137538 spdy::SpdyHeaderBlock request_headers0(
7539 spdy_util_.ConstructGetHeaderBlock(kUrl));
7540 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:097541 1, std::move(request_headers0), LOWEST, true));
7542
Ryan Hamilton0239aac2018-05-19 00:03:137543 spdy::SpdyHeaderBlock response_headers0;
7544 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:097545 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:137546 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:097547 1, std::move(response_headers0), true));
7548
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377549 // Stream 1 is closed.
7550 spdy_util_.UpdateWithStreamDestruction(1);
7551
7552 // Generate the NTLM messages based on known test data.
7553 std::string negotiate_msg;
7554 std::string challenge_msg;
7555 std::string authenticate_msg;
7556 base::Base64Encode(
7557 base::StringPiece(
7558 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247559 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377560 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557561 base::Base64Encode(
7562 base::StringPiece(
7563 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247564 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557565 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377566 base::Base64Encode(
7567 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097568 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557569 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247570 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557571 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377572 &authenticate_msg);
7573
7574 // Retry with authorization header.
Ryan Hamilton0239aac2018-05-19 00:03:137575 spdy::SpdyHeaderBlock request_headers1(
7576 spdy_util_.ConstructGetHeaderBlock(kUrl));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377577 request_headers1["authorization"] = std::string("NTLM ") + negotiate_msg;
Ryan Hamilton0239aac2018-05-19 00:03:137578 spdy::SpdySerializedFrame request1(spdy_util_.ConstructSpdyHeaders(
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377579 3, std::move(request_headers1), LOWEST, true));
7580
Ryan Hamilton0239aac2018-05-19 00:03:137581 spdy::SpdySerializedFrame rst(
7582 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377583
Bence Béky3238f2e12017-09-22 22:44:497584 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
7585 MockRead reads0[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)};
Bence Béky83eb3512017-09-05 12:56:097586
7587 // Retry yet again using HTTP/1.1.
7588 MockWrite writes1[] = {
7589 // After restarting with a null identity, this is the
7590 // request we should be issuing -- the final header line contains a Type
7591 // 1 message.
7592 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557593 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097594 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377595 "Authorization: NTLM "),
7596 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097597
7598 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7599 // (the credentials for the origin server). The second request continues
7600 // on the same connection.
7601 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557602 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097603 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377604 "Authorization: NTLM "),
7605 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097606 };
7607
7608 MockRead reads1[] = {
7609 // The origin server responds with a Type 2 message.
7610 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377611 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7612 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:097613 MockRead("Content-Type: text/html\r\n\r\n"),
7614 MockRead("You are not authorized to view this page\r\n"),
7615
7616 // Lastly we get the desired content.
7617 MockRead("HTTP/1.1 200 OK\r\n"),
7618 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027619 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:097620 };
Ryan Sleevib8d7ea02018-05-07 20:01:017621 SequencedSocketData data0(reads0, writes0);
7622 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:097623 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7624 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7625
7626 SSLSocketDataProvider ssl0(ASYNC, OK);
7627 ssl0.next_proto = kProtoHTTP2;
7628 SSLSocketDataProvider ssl1(ASYNC, OK);
7629 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7630 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7631
7632 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7633 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7634
7635 TestCompletionCallback callback1;
7636 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
7637 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7638
7639 rv = callback1.WaitForResult();
7640 EXPECT_THAT(rv, IsOk());
7641
7642 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7643
7644 const HttpResponseInfo* response = trans.GetResponseInfo();
7645 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587646 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:097647
7648 TestCompletionCallback callback2;
7649
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377650 rv = trans.RestartWithAuth(
7651 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7652 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:097653 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7654
7655 rv = callback2.WaitForResult();
7656 EXPECT_THAT(rv, IsOk());
7657
7658 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7659
7660 response = trans.GetResponseInfo();
7661 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587662 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:097663
7664 TestCompletionCallback callback3;
7665
7666 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
7667 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7668
7669 rv = callback3.WaitForResult();
7670 EXPECT_THAT(rv, IsOk());
7671
7672 response = trans.GetResponseInfo();
7673 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587674 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027675 EXPECT_EQ(14, response->headers->GetContentLength());
7676
7677 std::string response_data;
7678 rv = ReadTransaction(&trans, &response_data);
7679 EXPECT_THAT(rv, IsOk());
7680 EXPECT_EQ("Please Login\r\n", response_data);
7681
7682 EXPECT_TRUE(data0.AllReadDataConsumed());
7683 EXPECT_TRUE(data0.AllWriteDataConsumed());
7684 EXPECT_TRUE(data1.AllReadDataConsumed());
7685 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:097686}
David Benjamin5cb91132018-04-06 05:54:497687
7688// Test that, if we have an NTLM proxy and the origin resets the connection, we
7689// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:377690// regression test for https://crbug.com/823387. The version interference probe
7691// has since been removed, but retain the regression test so we can update it if
7692// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:497693TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
7694 // The NTLM test data expects the proxy to be named 'server'. The origin is
7695 // https://origin/.
7696 session_deps_.proxy_resolution_service =
7697 ProxyResolutionService::CreateFixedFromPacResult(
7698 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
7699
7700 SSLConfig config;
David Benjamin5cb91132018-04-06 05:54:497701 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:077702 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:497703
7704 HttpRequestInfo request;
7705 request.method = "GET";
7706 request.url = GURL("https://origin/");
7707 request.traffic_annotation =
7708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7709
7710 // Ensure load is not disrupted by flags which suppress behaviour specific
7711 // to other auth schemes.
7712 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
7713
7714 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7715 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7716 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7717
7718 // Generate the NTLM messages based on known test data.
7719 std::string negotiate_msg;
7720 std::string challenge_msg;
7721 std::string authenticate_msg;
7722 base::Base64Encode(
7723 base::StringPiece(
7724 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247725 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:497726 &negotiate_msg);
7727 base::Base64Encode(
7728 base::StringPiece(
7729 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247730 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:497731 &challenge_msg);
7732 base::Base64Encode(
7733 base::StringPiece(
7734 reinterpret_cast<const char*>(
7735 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247736 base::size(
David Benjamin5cb91132018-04-06 05:54:497737 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7738 &authenticate_msg);
7739
7740 MockWrite data_writes[] = {
7741 // The initial CONNECT request.
7742 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7743 "Host: origin:443\r\n"
7744 "Proxy-Connection: keep-alive\r\n\r\n"),
7745
7746 // After restarting with an identity.
7747 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7748 "Host: origin:443\r\n"
7749 "Proxy-Connection: keep-alive\r\n"
7750 "Proxy-Authorization: NTLM "),
7751 MockWrite(negotiate_msg.c_str()),
7752 // End headers.
7753 MockWrite("\r\n\r\n"),
7754
7755 // The second restart.
7756 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7757 "Host: origin:443\r\n"
7758 "Proxy-Connection: keep-alive\r\n"
7759 "Proxy-Authorization: NTLM "),
7760 MockWrite(authenticate_msg.c_str()),
7761 // End headers.
7762 MockWrite("\r\n\r\n"),
7763 };
7764
7765 MockRead data_reads[] = {
7766 // The initial NTLM response.
7767 MockRead("HTTP/1.1 407 Access Denied\r\n"
7768 "Content-Length: 0\r\n"
7769 "Proxy-Authenticate: NTLM\r\n\r\n"),
7770
7771 // The NTLM challenge message.
7772 MockRead("HTTP/1.1 407 Access Denied\r\n"
7773 "Content-Length: 0\r\n"
7774 "Proxy-Authenticate: NTLM "),
7775 MockRead(challenge_msg.c_str()),
7776 // End headers.
7777 MockRead("\r\n\r\n"),
7778
7779 // Finally the tunnel is established.
7780 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
7781 };
7782
Ryan Sleevib8d7ea02018-05-07 20:01:017783 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:497784 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:497785 session_deps_.socket_factory->AddSocketDataProvider(&data);
7786 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:497787
7788 // Start the transaction. The proxy responds with an NTLM authentication
7789 // request.
7790 TestCompletionCallback callback;
7791 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7792 int rv = callback.GetResult(
7793 trans.Start(&request, callback.callback(), NetLogWithSource()));
7794
7795 EXPECT_THAT(rv, IsOk());
7796 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7797 const HttpResponseInfo* response = trans.GetResponseInfo();
7798 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587799 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:497800
David Benjamind61bd532019-04-23 21:11:377801 // Configure credentials and restart. The proxy responds with the challenge
7802 // message.
David Benjamin5cb91132018-04-06 05:54:497803 rv = callback.GetResult(trans.RestartWithAuth(
7804 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7805 callback.callback()));
7806 EXPECT_THAT(rv, IsOk());
7807 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7808 response = trans.GetResponseInfo();
7809 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587810 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:497811
David Benjamind61bd532019-04-23 21:11:377812 // Restart once more. The tunnel will be established and then the SSL
7813 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:497814 rv = callback.GetResult(
7815 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
7816 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
7817}
7818
[email protected]ea9dc9a2009-09-05 00:43:327819#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:297820
[email protected]4ddaf2502008-10-23 18:26:197821// Test reading a server response which has only headers, and no body.
7822// After some maximum number of bytes is consumed, the transaction should
7823// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:017824TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:427825 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:197826 request.method = "GET";
bncce36dca22015-04-21 22:11:237827 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107828 request.traffic_annotation =
7829 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:197830
danakj1fd259a02016-04-16 03:17:097831 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:167832 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277833
[email protected]b75b7b2f2009-10-06 00:54:537834 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:437835 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:537836 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:197837
7838 MockRead data_reads[] = {
7839 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:067840 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:197841 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:067842 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:197843 };
Ryan Sleevib8d7ea02018-05-07 20:01:017844 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077845 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:197846
[email protected]49639fa2011-12-20 23:22:417847 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:197848
tfarina42834112016-09-22 13:38:207849 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017850 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:197851
7852 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017853 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:197854}
[email protected]f4e426b2008-11-05 00:24:497855
7856// Make sure that we don't try to reuse a TCPClientSocket when failing to
7857// establish tunnel.
7858// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:017859TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:277860 HttpRequestInfo request;
7861 request.method = "GET";
bncce36dca22015-04-21 22:11:237862 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107863 request.traffic_annotation =
7864 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277865
[email protected]f4e426b2008-11-05 00:24:497866 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497867 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7868 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:017869
danakj1fd259a02016-04-16 03:17:097870 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:497871
bnc87dcefc2017-05-25 12:47:587872 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197873 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:497874
[email protected]f4e426b2008-11-05 00:24:497875 // Since we have proxy, should try to establish tunnel.
7876 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:177877 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7878 "Host: www.example.org:443\r\n"
7879 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:497880 };
7881
[email protected]77848d12008-11-14 00:00:227882 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:497883 // connection. Usually a proxy would return 501 (not implemented),
7884 // or 200 (tunnel established).
7885 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:237886 MockRead("HTTP/1.1 404 Not Found\r\n"),
7887 MockRead("Content-Length: 10\r\n\r\n"),
7888 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:497889 };
7890
Ryan Sleevib8d7ea02018-05-07 20:01:017891 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077892 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:497893
[email protected]49639fa2011-12-20 23:22:417894 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:497895
tfarina42834112016-09-22 13:38:207896 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017897 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:497898
7899 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017900 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:497901
[email protected]b4404c02009-04-10 16:38:527902 // Empty the current queue. This is necessary because idle sockets are
7903 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557904 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:527905
[email protected]f4e426b2008-11-05 00:24:497906 // We now check to make sure the TCPClientSocket was not added back to
7907 // the pool.
[email protected]90499482013-06-01 00:39:507908 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497909 trans.reset();
fdoray92e35a72016-06-10 15:54:557910 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:497911 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:507912 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497913}
[email protected]372d34a2008-11-05 21:30:517914
[email protected]1b157c02009-04-21 01:55:407915// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:017916TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:427917 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:407918 request.method = "GET";
bncce36dca22015-04-21 22:11:237919 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107920 request.traffic_annotation =
7921 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:407922
danakj1fd259a02016-04-16 03:17:097923 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277924
bnc691fda62016-08-12 00:43:167925 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277926
[email protected]1b157c02009-04-21 01:55:407927 MockRead data_reads[] = {
7928 // A part of the response body is received with the response headers.
7929 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
7930 // The rest of the response body is received in two parts.
7931 MockRead("lo"),
7932 MockRead(" world"),
7933 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:067934 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:407935 };
7936
Ryan Sleevib8d7ea02018-05-07 20:01:017937 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077938 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:407939
[email protected]49639fa2011-12-20 23:22:417940 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:407941
tfarina42834112016-09-22 13:38:207942 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:407944
7945 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017946 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407947
bnc691fda62016-08-12 00:43:167948 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527949 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:407950
wezca1070932016-05-26 20:30:527951 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:407952 std::string status_line = response->headers->GetStatusLine();
7953 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
7954
[email protected]90499482013-06-01 00:39:507955 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407956
7957 std::string response_data;
bnc691fda62016-08-12 00:43:167958 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:017959 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407960 EXPECT_EQ("hello world", response_data);
7961
7962 // Empty the current queue. This is necessary because idle sockets are
7963 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557964 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:407965
7966 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:507967 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407968}
7969
[email protected]76a505b2010-08-25 06:23:007970// Make sure that we recycle a SSL socket after reading all of the response
7971// body.
bncd16676a2016-07-20 16:23:017972TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:007973 HttpRequestInfo request;
7974 request.method = "GET";
bncce36dca22015-04-21 22:11:237975 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107976 request.traffic_annotation =
7977 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:007978
7979 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237980 MockWrite(
7981 "GET / HTTP/1.1\r\n"
7982 "Host: www.example.org\r\n"
7983 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:007984 };
7985
7986 MockRead data_reads[] = {
7987 MockRead("HTTP/1.1 200 OK\r\n"),
7988 MockRead("Content-Length: 11\r\n\r\n"),
7989 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:067990 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:007991 };
7992
[email protected]8ddf8322012-02-23 18:08:067993 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077994 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:007995
Ryan Sleevib8d7ea02018-05-07 20:01:017996 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:077997 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:007998
[email protected]49639fa2011-12-20 23:22:417999 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008000
danakj1fd259a02016-04-16 03:17:098001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168002 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008003
tfarina42834112016-09-22 13:38:208004 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008005
robpercival214763f2016-07-01 23:27:018006 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8007 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008008
bnc691fda62016-08-12 00:43:168009 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528010 ASSERT_TRUE(response);
8011 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008012 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8013
[email protected]90499482013-06-01 00:39:508014 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008015
8016 std::string response_data;
bnc691fda62016-08-12 00:43:168017 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018018 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008019 EXPECT_EQ("hello world", response_data);
8020
8021 // Empty the current queue. This is necessary because idle sockets are
8022 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558023 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008024
8025 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238026 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008027}
8028
8029// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8030// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018031TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008032 HttpRequestInfo request;
8033 request.method = "GET";
bncce36dca22015-04-21 22:11:238034 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108035 request.traffic_annotation =
8036 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008037
8038 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238039 MockWrite(
8040 "GET / HTTP/1.1\r\n"
8041 "Host: www.example.org\r\n"
8042 "Connection: keep-alive\r\n\r\n"),
8043 MockWrite(
8044 "GET / HTTP/1.1\r\n"
8045 "Host: www.example.org\r\n"
8046 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008047 };
8048
8049 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428050 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8051 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008052
[email protected]8ddf8322012-02-23 18:08:068053 SSLSocketDataProvider ssl(ASYNC, OK);
8054 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078055 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8056 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008057
Ryan Sleevib8d7ea02018-05-07 20:01:018058 StaticSocketDataProvider data(data_reads, data_writes);
8059 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078060 session_deps_.socket_factory->AddSocketDataProvider(&data);
8061 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008062
[email protected]49639fa2011-12-20 23:22:418063 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008064
danakj1fd259a02016-04-16 03:17:098065 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588066 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198067 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008068
tfarina42834112016-09-22 13:38:208069 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008070
robpercival214763f2016-07-01 23:27:018071 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8072 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008073
8074 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528075 ASSERT_TRUE(response);
8076 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008077 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8078
[email protected]90499482013-06-01 00:39:508079 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008080
8081 std::string response_data;
8082 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018083 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008084 EXPECT_EQ("hello world", response_data);
8085
8086 // Empty the current queue. This is necessary because idle sockets are
8087 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558088 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008089
8090 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238091 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008092
8093 // Now start the second transaction, which should reuse the previous socket.
8094
bnc87dcefc2017-05-25 12:47:588095 trans =
Jeremy Roman0579ed62017-08-29 15:56:198096 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008097
tfarina42834112016-09-22 13:38:208098 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008099
robpercival214763f2016-07-01 23:27:018100 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8101 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008102
8103 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528104 ASSERT_TRUE(response);
8105 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008106 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8107
[email protected]90499482013-06-01 00:39:508108 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008109
8110 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018111 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008112 EXPECT_EQ("hello world", response_data);
8113
8114 // Empty the current queue. This is necessary because idle sockets are
8115 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558116 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008117
8118 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238119 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008120}
8121
maksim.sisov0adf8592016-07-15 06:25:568122// Grab a socket, use it, and put it back into the pool. Then, make
8123// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018124TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568125 HttpRequestInfo request;
8126 request.method = "GET";
8127 request.url = GURL("http://www.example.org/");
8128 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108129 request.traffic_annotation =
8130 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568131
8132 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8133
bnc691fda62016-08-12 00:43:168134 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568135
8136 MockRead data_reads[] = {
8137 // A part of the response body is received with the response headers.
8138 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8139 // The rest of the response body is received in two parts.
8140 MockRead("lo"), MockRead(" world"),
8141 MockRead("junk"), // Should not be read!!
8142 MockRead(SYNCHRONOUS, OK),
8143 };
8144
Ryan Sleevib8d7ea02018-05-07 20:01:018145 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:568146 session_deps_.socket_factory->AddSocketDataProvider(&data);
8147
8148 TestCompletionCallback callback;
8149
tfarina42834112016-09-22 13:38:208150 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568151 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8152
8153 EXPECT_THAT(callback.GetResult(rv), IsOk());
8154
bnc691fda62016-08-12 00:43:168155 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568156 ASSERT_TRUE(response);
8157 EXPECT_TRUE(response->headers);
8158 std::string status_line = response->headers->GetStatusLine();
8159 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8160
8161 // Make memory critical notification and ensure the transaction still has been
8162 // operating right.
8163 base::MemoryPressureListener::NotifyMemoryPressure(
8164 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8165 base::RunLoop().RunUntilIdle();
8166
8167 // Socket should not be flushed as long as it is not idle.
8168 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8169
8170 std::string response_data;
bnc691fda62016-08-12 00:43:168171 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568172 EXPECT_THAT(rv, IsOk());
8173 EXPECT_EQ("hello world", response_data);
8174
8175 // Empty the current queue. This is necessary because idle sockets are
8176 // added to the connection pool asynchronously with a PostTask.
8177 base::RunLoop().RunUntilIdle();
8178
8179 // We now check to make sure the socket was added back to the pool.
8180 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8181
8182 // Idle sockets should be flushed now.
8183 base::MemoryPressureListener::NotifyMemoryPressure(
8184 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8185 base::RunLoop().RunUntilIdle();
8186
8187 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8188}
8189
yucliu48f235d2018-01-11 00:59:558190// Disable idle socket closing on memory pressure.
8191// Grab a socket, use it, and put it back into the pool. Then, make
8192// low memory notification and ensure the socket pool is NOT flushed.
8193TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
8194 HttpRequestInfo request;
8195 request.method = "GET";
8196 request.url = GURL("http://www.example.org/");
8197 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108198 request.traffic_annotation =
8199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:558200
8201 // Disable idle socket closing on memory pressure.
8202 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
8203 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8204
8205 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8206
8207 MockRead data_reads[] = {
8208 // A part of the response body is received with the response headers.
8209 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8210 // The rest of the response body is received in two parts.
8211 MockRead("lo"), MockRead(" world"),
8212 MockRead("junk"), // Should not be read!!
8213 MockRead(SYNCHRONOUS, OK),
8214 };
8215
Ryan Sleevib8d7ea02018-05-07 20:01:018216 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:558217 session_deps_.socket_factory->AddSocketDataProvider(&data);
8218
8219 TestCompletionCallback callback;
8220
8221 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
8222 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8223
8224 EXPECT_THAT(callback.GetResult(rv), IsOk());
8225
8226 const HttpResponseInfo* response = trans.GetResponseInfo();
8227 ASSERT_TRUE(response);
8228 EXPECT_TRUE(response->headers);
8229 std::string status_line = response->headers->GetStatusLine();
8230 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8231
8232 // Make memory critical notification and ensure the transaction still has been
8233 // operating right.
8234 base::MemoryPressureListener::NotifyMemoryPressure(
8235 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8236 base::RunLoop().RunUntilIdle();
8237
8238 // Socket should not be flushed as long as it is not idle.
8239 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8240
8241 std::string response_data;
8242 rv = ReadTransaction(&trans, &response_data);
8243 EXPECT_THAT(rv, IsOk());
8244 EXPECT_EQ("hello world", response_data);
8245
8246 // Empty the current queue. This is necessary because idle sockets are
8247 // added to the connection pool asynchronously with a PostTask.
8248 base::RunLoop().RunUntilIdle();
8249
8250 // We now check to make sure the socket was added back to the pool.
8251 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8252
8253 // Idle sockets should NOT be flushed on moderate memory pressure.
8254 base::MemoryPressureListener::NotifyMemoryPressure(
8255 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
8256 base::RunLoop().RunUntilIdle();
8257
8258 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8259
8260 // Idle sockets should NOT be flushed on critical memory pressure.
8261 base::MemoryPressureListener::NotifyMemoryPressure(
8262 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8263 base::RunLoop().RunUntilIdle();
8264
8265 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8266}
8267
maksim.sisov0adf8592016-07-15 06:25:568268// Grab an SSL socket, use it, and put it back into the pool. Then, make
8269// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018270TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568271 HttpRequestInfo request;
8272 request.method = "GET";
8273 request.url = GURL("https://www.example.org/");
8274 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108275 request.traffic_annotation =
8276 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568277
8278 MockWrite data_writes[] = {
8279 MockWrite("GET / HTTP/1.1\r\n"
8280 "Host: www.example.org\r\n"
8281 "Connection: keep-alive\r\n\r\n"),
8282 };
8283
8284 MockRead data_reads[] = {
8285 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8286 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
8287
8288 SSLSocketDataProvider ssl(ASYNC, OK);
8289 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8290
Ryan Sleevib8d7ea02018-05-07 20:01:018291 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:568292 session_deps_.socket_factory->AddSocketDataProvider(&data);
8293
8294 TestCompletionCallback callback;
8295
8296 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168297 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568298
Matt Menke9d5e2c92019-02-05 01:42:238299 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:208300 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568301
8302 EXPECT_THAT(callback.GetResult(rv), IsOk());
8303
bnc691fda62016-08-12 00:43:168304 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568305 ASSERT_TRUE(response);
8306 ASSERT_TRUE(response->headers);
8307 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8308
8309 // Make memory critical notification and ensure the transaction still has been
8310 // operating right.
8311 base::MemoryPressureListener::NotifyMemoryPressure(
8312 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8313 base::RunLoop().RunUntilIdle();
8314
Matt Menke9d5e2c92019-02-05 01:42:238315 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568316
8317 std::string response_data;
bnc691fda62016-08-12 00:43:168318 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568319 EXPECT_THAT(rv, IsOk());
8320 EXPECT_EQ("hello world", response_data);
8321
8322 // Empty the current queue. This is necessary because idle sockets are
8323 // added to the connection pool asynchronously with a PostTask.
8324 base::RunLoop().RunUntilIdle();
8325
8326 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238327 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568328
8329 // Make memory notification once again and ensure idle socket is closed.
8330 base::MemoryPressureListener::NotifyMemoryPressure(
8331 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8332 base::RunLoop().RunUntilIdle();
8333
Matt Menke9d5e2c92019-02-05 01:42:238334 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568335}
8336
[email protected]b4404c02009-04-10 16:38:528337// Make sure that we recycle a socket after a zero-length response.
8338// http://crbug.com/9880
bncd16676a2016-07-20 16:23:018339TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:428340 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:528341 request.method = "GET";
bncce36dca22015-04-21 22:11:238342 request.url = GURL(
8343 "http://www.example.org/csi?v=3&s=web&action=&"
8344 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
8345 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
8346 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:108347 request.traffic_annotation =
8348 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:528349
danakj1fd259a02016-04-16 03:17:098350 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278351
[email protected]b4404c02009-04-10 16:38:528352 MockRead data_reads[] = {
8353 MockRead("HTTP/1.1 204 No Content\r\n"
8354 "Content-Length: 0\r\n"
8355 "Content-Type: text/html\r\n\r\n"),
8356 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068357 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:528358 };
8359
Ryan Sleevib8d7ea02018-05-07 20:01:018360 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078361 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:528362
mmenkecc2298e2015-12-07 18:20:188363 // Transaction must be created after the MockReads, so it's destroyed before
8364 // them.
bnc691fda62016-08-12 00:43:168365 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:188366
[email protected]49639fa2011-12-20 23:22:418367 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:528368
tfarina42834112016-09-22 13:38:208369 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018370 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:528371
8372 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018373 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528374
bnc691fda62016-08-12 00:43:168375 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528376 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:528377
wezca1070932016-05-26 20:30:528378 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:528379 std::string status_line = response->headers->GetStatusLine();
8380 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
8381
[email protected]90499482013-06-01 00:39:508382 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528383
8384 std::string response_data;
bnc691fda62016-08-12 00:43:168385 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018386 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528387 EXPECT_EQ("", response_data);
8388
8389 // Empty the current queue. This is necessary because idle sockets are
8390 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558391 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528392
8393 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508394 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528395}
8396
bncd16676a2016-07-20 16:23:018397TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:098398 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:228399 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:198400 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:228401 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:278402
[email protected]1c773ea12009-04-28 19:58:428403 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:518404 // Transaction 1: a GET request that succeeds. The socket is recycled
8405 // after use.
8406 request[0].method = "GET";
8407 request[0].url = GURL("http://www.google.com/");
8408 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108409 request[0].traffic_annotation =
8410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518411 // Transaction 2: a POST request. Reuses the socket kept alive from
8412 // transaction 1. The first attempts fails when writing the POST data.
8413 // This causes the transaction to retry with a new socket. The second
8414 // attempt succeeds.
8415 request[1].method = "POST";
8416 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:278417 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:518418 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108419 request[1].traffic_annotation =
8420 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518421
danakj1fd259a02016-04-16 03:17:098422 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:518423
8424 // The first socket is used for transaction 1 and the first attempt of
8425 // transaction 2.
8426
8427 // The response of transaction 1.
8428 MockRead data_reads1[] = {
8429 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
8430 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068431 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518432 };
8433 // The mock write results of transaction 1 and the first attempt of
8434 // transaction 2.
8435 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:068436 MockWrite(SYNCHRONOUS, 64), // GET
8437 MockWrite(SYNCHRONOUS, 93), // POST
8438 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:518439 };
Ryan Sleevib8d7ea02018-05-07 20:01:018440 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:518441
8442 // The second socket is used for the second attempt of transaction 2.
8443
8444 // The response of transaction 2.
8445 MockRead data_reads2[] = {
8446 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
8447 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:068448 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518449 };
8450 // The mock write results of the second attempt of transaction 2.
8451 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:068452 MockWrite(SYNCHRONOUS, 93), // POST
8453 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:518454 };
Ryan Sleevib8d7ea02018-05-07 20:01:018455 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:518456
[email protected]bb88e1d32013-05-03 23:11:078457 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8458 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:518459
thestig9d3bb0c2015-01-24 00:49:518460 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:518461 "hello world", "welcome"
8462 };
8463
8464 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:168465 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:518466
[email protected]49639fa2011-12-20 23:22:418467 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:518468
tfarina42834112016-09-22 13:38:208469 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:518471
8472 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018473 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518474
bnc691fda62016-08-12 00:43:168475 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528476 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:518477
wezca1070932016-05-26 20:30:528478 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:518479 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8480
8481 std::string response_data;
bnc691fda62016-08-12 00:43:168482 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018483 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518484 EXPECT_EQ(kExpectedResponseData[i], response_data);
8485 }
8486}
[email protected]f9ee6b52008-11-08 06:46:238487
8488// Test the request-challenge-retry sequence for basic auth when there is
8489// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:168490// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:018491TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:428492 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238493 request.method = "GET";
bncce36dca22015-04-21 22:11:238494 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:418495 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108496 request.traffic_annotation =
8497 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:298498
danakj1fd259a02016-04-16 03:17:098499 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168500 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278501
[email protected]a97cca42009-08-14 01:00:298502 // The password contains an escaped character -- for this test to pass it
8503 // will need to be unescaped by HttpNetworkTransaction.
8504 EXPECT_EQ("b%40r", request.url.password());
8505
[email protected]f9ee6b52008-11-08 06:46:238506 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238507 MockWrite(
8508 "GET / HTTP/1.1\r\n"
8509 "Host: www.example.org\r\n"
8510 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238511 };
8512
8513 MockRead data_reads1[] = {
8514 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8515 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8516 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068517 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238518 };
8519
[email protected]2262e3a2012-05-22 16:08:168520 // After the challenge above, the transaction will be restarted using the
8521 // identity from the url (foo, b@r) to answer the challenge.
8522 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238523 MockWrite(
8524 "GET / HTTP/1.1\r\n"
8525 "Host: www.example.org\r\n"
8526 "Connection: keep-alive\r\n"
8527 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168528 };
8529
8530 MockRead data_reads2[] = {
8531 MockRead("HTTP/1.0 200 OK\r\n"),
8532 MockRead("Content-Length: 100\r\n\r\n"),
8533 MockRead(SYNCHRONOUS, OK),
8534 };
8535
Ryan Sleevib8d7ea02018-05-07 20:01:018536 StaticSocketDataProvider data1(data_reads1, data_writes1);
8537 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078538 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8539 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238540
[email protected]49639fa2011-12-20 23:22:418541 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208542 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018543 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238544 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018545 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168546 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168547
8548 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168549 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018550 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168551 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018552 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168553 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228554
bnc691fda62016-08-12 00:43:168555 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528556 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168557
8558 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:588559 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168560
8561 EXPECT_EQ(100, response->headers->GetContentLength());
8562
8563 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558564 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:168565}
8566
8567// Test the request-challenge-retry sequence for basic auth when there is an
8568// incorrect identity in the URL. The identity from the URL should be used only
8569// once.
bncd16676a2016-07-20 16:23:018570TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:168571 HttpRequestInfo request;
8572 request.method = "GET";
8573 // Note: the URL has a username:password in it. The password "baz" is
8574 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:238575 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:168576
8577 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108578 request.traffic_annotation =
8579 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:168580
danakj1fd259a02016-04-16 03:17:098581 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168582 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:168583
8584 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238585 MockWrite(
8586 "GET / HTTP/1.1\r\n"
8587 "Host: www.example.org\r\n"
8588 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168589 };
8590
8591 MockRead data_reads1[] = {
8592 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8593 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8594 MockRead("Content-Length: 10\r\n\r\n"),
8595 MockRead(SYNCHRONOUS, ERR_FAILED),
8596 };
8597
8598 // After the challenge above, the transaction will be restarted using the
8599 // identity from the url (foo, baz) to answer the challenge.
8600 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238601 MockWrite(
8602 "GET / HTTP/1.1\r\n"
8603 "Host: www.example.org\r\n"
8604 "Connection: keep-alive\r\n"
8605 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168606 };
8607
8608 MockRead data_reads2[] = {
8609 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8610 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8611 MockRead("Content-Length: 10\r\n\r\n"),
8612 MockRead(SYNCHRONOUS, ERR_FAILED),
8613 };
8614
8615 // After the challenge above, the transaction will be restarted using the
8616 // identity supplied by the user (foo, bar) to answer the challenge.
8617 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238618 MockWrite(
8619 "GET / HTTP/1.1\r\n"
8620 "Host: www.example.org\r\n"
8621 "Connection: keep-alive\r\n"
8622 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168623 };
8624
8625 MockRead data_reads3[] = {
8626 MockRead("HTTP/1.0 200 OK\r\n"),
8627 MockRead("Content-Length: 100\r\n\r\n"),
8628 MockRead(SYNCHRONOUS, OK),
8629 };
8630
Ryan Sleevib8d7ea02018-05-07 20:01:018631 StaticSocketDataProvider data1(data_reads1, data_writes1);
8632 StaticSocketDataProvider data2(data_reads2, data_writes2);
8633 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078634 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8635 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8636 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:168637
8638 TestCompletionCallback callback1;
8639
tfarina42834112016-09-22 13:38:208640 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018641 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168642
8643 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018644 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:168645
bnc691fda62016-08-12 00:43:168646 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168647 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168648 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018649 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168650 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018651 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168652 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168653
bnc691fda62016-08-12 00:43:168654 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528655 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588656 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:168657
8658 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168659 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018660 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168661 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018662 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168663 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168664
bnc691fda62016-08-12 00:43:168665 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528666 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168667
8668 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588669 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168670
8671 EXPECT_EQ(100, response->headers->GetContentLength());
8672
[email protected]ea9dc9a2009-09-05 00:43:328673 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558674 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:328675}
8676
[email protected]2217aa22013-10-11 03:03:548677
8678// Test the request-challenge-retry sequence for basic auth when there is a
8679// correct identity in the URL, but its use is being suppressed. The identity
8680// from the URL should never be used.
bncd16676a2016-07-20 16:23:018681TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:548682 HttpRequestInfo request;
8683 request.method = "GET";
bncce36dca22015-04-21 22:11:238684 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:548685 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:108686 request.traffic_annotation =
8687 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548688
danakj1fd259a02016-04-16 03:17:098689 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168690 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:548691
8692 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238693 MockWrite(
8694 "GET / HTTP/1.1\r\n"
8695 "Host: www.example.org\r\n"
8696 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548697 };
8698
8699 MockRead data_reads1[] = {
8700 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8701 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8702 MockRead("Content-Length: 10\r\n\r\n"),
8703 MockRead(SYNCHRONOUS, ERR_FAILED),
8704 };
8705
8706 // After the challenge above, the transaction will be restarted using the
8707 // identity supplied by the user, not the one in the URL, to answer the
8708 // challenge.
8709 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238710 MockWrite(
8711 "GET / HTTP/1.1\r\n"
8712 "Host: www.example.org\r\n"
8713 "Connection: keep-alive\r\n"
8714 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548715 };
8716
8717 MockRead data_reads3[] = {
8718 MockRead("HTTP/1.0 200 OK\r\n"),
8719 MockRead("Content-Length: 100\r\n\r\n"),
8720 MockRead(SYNCHRONOUS, OK),
8721 };
8722
Ryan Sleevib8d7ea02018-05-07 20:01:018723 StaticSocketDataProvider data1(data_reads1, data_writes1);
8724 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:548725 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8726 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8727
8728 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208729 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018730 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548731 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018732 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168733 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548734
bnc691fda62016-08-12 00:43:168735 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528736 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588737 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:548738
8739 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168740 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018741 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548742 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018743 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168744 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548745
bnc691fda62016-08-12 00:43:168746 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528747 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:548748
8749 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588750 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:548751 EXPECT_EQ(100, response->headers->GetContentLength());
8752
8753 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558754 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:548755}
8756
[email protected]f9ee6b52008-11-08 06:46:238757// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:018758TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:098759 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:238760
8761 // Transaction 1: authenticate (foo, bar) on MyRealm1
8762 {
[email protected]1c773ea12009-04-28 19:58:428763 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238764 request.method = "GET";
bncce36dca22015-04-21 22:11:238765 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:108766 request.traffic_annotation =
8767 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238768
bnc691fda62016-08-12 00:43:168769 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278770
[email protected]f9ee6b52008-11-08 06:46:238771 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238772 MockWrite(
8773 "GET /x/y/z HTTP/1.1\r\n"
8774 "Host: www.example.org\r\n"
8775 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238776 };
8777
8778 MockRead data_reads1[] = {
8779 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8780 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8781 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068782 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238783 };
8784
8785 // Resend with authorization (username=foo, password=bar)
8786 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238787 MockWrite(
8788 "GET /x/y/z HTTP/1.1\r\n"
8789 "Host: www.example.org\r\n"
8790 "Connection: keep-alive\r\n"
8791 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238792 };
8793
8794 // Sever accepts the authorization.
8795 MockRead data_reads2[] = {
8796 MockRead("HTTP/1.0 200 OK\r\n"),
8797 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068798 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238799 };
8800
Ryan Sleevib8d7ea02018-05-07 20:01:018801 StaticSocketDataProvider data1(data_reads1, data_writes1);
8802 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078803 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8804 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238805
[email protected]49639fa2011-12-20 23:22:418806 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238807
tfarina42834112016-09-22 13:38:208808 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018809 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238810
8811 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018812 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238813
bnc691fda62016-08-12 00:43:168814 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528815 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588816 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:238817
[email protected]49639fa2011-12-20 23:22:418818 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238819
bnc691fda62016-08-12 00:43:168820 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
8821 callback2.callback());
robpercival214763f2016-07-01 23:27:018822 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238823
8824 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018825 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238826
bnc691fda62016-08-12 00:43:168827 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528828 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588829 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238830 EXPECT_EQ(100, response->headers->GetContentLength());
8831 }
8832
8833 // ------------------------------------------------------------------------
8834
8835 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
8836 {
[email protected]1c773ea12009-04-28 19:58:428837 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238838 request.method = "GET";
8839 // Note that Transaction 1 was at /x/y/z, so this is in the same
8840 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:238841 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:108842 request.traffic_annotation =
8843 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238844
bnc691fda62016-08-12 00:43:168845 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278846
[email protected]f9ee6b52008-11-08 06:46:238847 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238848 MockWrite(
8849 "GET /x/y/a/b HTTP/1.1\r\n"
8850 "Host: www.example.org\r\n"
8851 "Connection: keep-alive\r\n"
8852 // Send preemptive authorization for MyRealm1
8853 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238854 };
8855
8856 // The server didn't like the preemptive authorization, and
8857 // challenges us for a different realm (MyRealm2).
8858 MockRead data_reads1[] = {
8859 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8860 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
8861 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068862 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238863 };
8864
8865 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
8866 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238867 MockWrite(
8868 "GET /x/y/a/b HTTP/1.1\r\n"
8869 "Host: www.example.org\r\n"
8870 "Connection: keep-alive\r\n"
8871 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238872 };
8873
8874 // Sever accepts the authorization.
8875 MockRead data_reads2[] = {
8876 MockRead("HTTP/1.0 200 OK\r\n"),
8877 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068878 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238879 };
8880
Ryan Sleevib8d7ea02018-05-07 20:01:018881 StaticSocketDataProvider data1(data_reads1, data_writes1);
8882 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078883 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8884 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238885
[email protected]49639fa2011-12-20 23:22:418886 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238887
tfarina42834112016-09-22 13:38:208888 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018889 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238890
8891 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018892 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238893
bnc691fda62016-08-12 00:43:168894 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528895 ASSERT_TRUE(response);
8896 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:048897 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:438898 EXPECT_EQ("http://www.example.org",
8899 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:048900 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:198901 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:238902
[email protected]49639fa2011-12-20 23:22:418903 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238904
bnc691fda62016-08-12 00:43:168905 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
8906 callback2.callback());
robpercival214763f2016-07-01 23:27:018907 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238908
8909 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018910 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238911
bnc691fda62016-08-12 00:43:168912 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528913 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588914 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238915 EXPECT_EQ(100, response->headers->GetContentLength());
8916 }
8917
8918 // ------------------------------------------------------------------------
8919
8920 // Transaction 3: Resend a request in MyRealm's protection space --
8921 // succeed with preemptive authorization.
8922 {
[email protected]1c773ea12009-04-28 19:58:428923 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238924 request.method = "GET";
bncce36dca22015-04-21 22:11:238925 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:108926 request.traffic_annotation =
8927 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238928
bnc691fda62016-08-12 00:43:168929 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278930
[email protected]f9ee6b52008-11-08 06:46:238931 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238932 MockWrite(
8933 "GET /x/y/z2 HTTP/1.1\r\n"
8934 "Host: www.example.org\r\n"
8935 "Connection: keep-alive\r\n"
8936 // The authorization for MyRealm1 gets sent preemptively
8937 // (since the url is in the same protection space)
8938 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238939 };
8940
8941 // Sever accepts the preemptive authorization
8942 MockRead data_reads1[] = {
8943 MockRead("HTTP/1.0 200 OK\r\n"),
8944 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068945 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238946 };
8947
Ryan Sleevib8d7ea02018-05-07 20:01:018948 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078949 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:238950
[email protected]49639fa2011-12-20 23:22:418951 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238952
tfarina42834112016-09-22 13:38:208953 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018954 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238955
8956 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018957 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238958
bnc691fda62016-08-12 00:43:168959 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528960 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:238961
Emily Starkf2c9bbd2019-04-09 17:08:588962 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238963 EXPECT_EQ(100, response->headers->GetContentLength());
8964 }
8965
8966 // ------------------------------------------------------------------------
8967
8968 // Transaction 4: request another URL in MyRealm (however the
8969 // url is not known to belong to the protection space, so no pre-auth).
8970 {
[email protected]1c773ea12009-04-28 19:58:428971 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238972 request.method = "GET";
bncce36dca22015-04-21 22:11:238973 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:108974 request.traffic_annotation =
8975 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238976
bnc691fda62016-08-12 00:43:168977 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278978
[email protected]f9ee6b52008-11-08 06:46:238979 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238980 MockWrite(
8981 "GET /x/1 HTTP/1.1\r\n"
8982 "Host: www.example.org\r\n"
8983 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238984 };
8985
8986 MockRead data_reads1[] = {
8987 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8988 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8989 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068990 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238991 };
8992
8993 // Resend with authorization from MyRealm's cache.
8994 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238995 MockWrite(
8996 "GET /x/1 HTTP/1.1\r\n"
8997 "Host: www.example.org\r\n"
8998 "Connection: keep-alive\r\n"
8999 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239000 };
9001
9002 // Sever accepts the authorization.
9003 MockRead data_reads2[] = {
9004 MockRead("HTTP/1.0 200 OK\r\n"),
9005 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069006 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239007 };
9008
Ryan Sleevib8d7ea02018-05-07 20:01:019009 StaticSocketDataProvider data1(data_reads1, data_writes1);
9010 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079011 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9012 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239013
[email protected]49639fa2011-12-20 23:22:419014 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239015
tfarina42834112016-09-22 13:38:209016 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019017 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239018
9019 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019020 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239021
bnc691fda62016-08-12 00:43:169022 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419023 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169024 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019025 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229026 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019027 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169028 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229029
bnc691fda62016-08-12 00:43:169030 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529031 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589032 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239033 EXPECT_EQ(100, response->headers->GetContentLength());
9034 }
9035
9036 // ------------------------------------------------------------------------
9037
9038 // Transaction 5: request a URL in MyRealm, but the server rejects the
9039 // cached identity. Should invalidate and re-prompt.
9040 {
[email protected]1c773ea12009-04-28 19:58:429041 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239042 request.method = "GET";
bncce36dca22015-04-21 22:11:239043 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:109044 request.traffic_annotation =
9045 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239046
bnc691fda62016-08-12 00:43:169047 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279048
[email protected]f9ee6b52008-11-08 06:46:239049 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239050 MockWrite(
9051 "GET /p/q/t HTTP/1.1\r\n"
9052 "Host: www.example.org\r\n"
9053 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239054 };
9055
9056 MockRead data_reads1[] = {
9057 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9058 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9059 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069060 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239061 };
9062
9063 // Resend with authorization from cache for MyRealm.
9064 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239065 MockWrite(
9066 "GET /p/q/t HTTP/1.1\r\n"
9067 "Host: www.example.org\r\n"
9068 "Connection: keep-alive\r\n"
9069 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239070 };
9071
9072 // Sever rejects the authorization.
9073 MockRead data_reads2[] = {
9074 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9075 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9076 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069077 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239078 };
9079
9080 // At this point we should prompt for new credentials for MyRealm.
9081 // Restart with username=foo3, password=foo4.
9082 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239083 MockWrite(
9084 "GET /p/q/t HTTP/1.1\r\n"
9085 "Host: www.example.org\r\n"
9086 "Connection: keep-alive\r\n"
9087 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239088 };
9089
9090 // Sever accepts the authorization.
9091 MockRead data_reads3[] = {
9092 MockRead("HTTP/1.0 200 OK\r\n"),
9093 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069094 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239095 };
9096
Ryan Sleevib8d7ea02018-05-07 20:01:019097 StaticSocketDataProvider data1(data_reads1, data_writes1);
9098 StaticSocketDataProvider data2(data_reads2, data_writes2);
9099 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079100 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9101 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9102 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239103
[email protected]49639fa2011-12-20 23:22:419104 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239105
tfarina42834112016-09-22 13:38:209106 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019107 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239108
9109 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019110 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239111
bnc691fda62016-08-12 00:43:169112 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419113 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169114 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019115 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229116 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019117 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169118 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229119
bnc691fda62016-08-12 00:43:169120 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529121 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589122 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239123
[email protected]49639fa2011-12-20 23:22:419124 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239125
bnc691fda62016-08-12 00:43:169126 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9127 callback3.callback());
robpercival214763f2016-07-01 23:27:019128 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239129
[email protected]0757e7702009-03-27 04:00:229130 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019131 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239132
bnc691fda62016-08-12 00:43:169133 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529134 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589135 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239136 EXPECT_EQ(100, response->headers->GetContentLength());
9137 }
9138}
[email protected]89ceba9a2009-03-21 03:46:069139
[email protected]3c32c5f2010-05-18 15:18:129140// Tests that nonce count increments when multiple auth attempts
9141// are started with the same nonce.
bncd16676a2016-07-20 16:23:019142TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449143 HttpAuthHandlerDigest::Factory* digest_factory =
9144 new HttpAuthHandlerDigest::Factory();
9145 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
9146 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
9147 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:079148 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:099149 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:129150
9151 // Transaction 1: authenticate (foo, bar) on MyRealm1
9152 {
[email protected]3c32c5f2010-05-18 15:18:129153 HttpRequestInfo request;
9154 request.method = "GET";
bncce36dca22015-04-21 22:11:239155 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109156 request.traffic_annotation =
9157 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129158
bnc691fda62016-08-12 00:43:169159 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279160
[email protected]3c32c5f2010-05-18 15:18:129161 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239162 MockWrite(
9163 "GET /x/y/z HTTP/1.1\r\n"
9164 "Host: www.example.org\r\n"
9165 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129166 };
9167
9168 MockRead data_reads1[] = {
9169 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9170 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
9171 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069172 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129173 };
9174
9175 // Resend with authorization (username=foo, password=bar)
9176 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239177 MockWrite(
9178 "GET /x/y/z HTTP/1.1\r\n"
9179 "Host: www.example.org\r\n"
9180 "Connection: keep-alive\r\n"
9181 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9182 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
9183 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
9184 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129185 };
9186
9187 // Sever accepts the authorization.
9188 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:089189 MockRead("HTTP/1.0 200 OK\r\n"),
9190 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129191 };
9192
Ryan Sleevib8d7ea02018-05-07 20:01:019193 StaticSocketDataProvider data1(data_reads1, data_writes1);
9194 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079195 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9196 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:129197
[email protected]49639fa2011-12-20 23:22:419198 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129199
tfarina42834112016-09-22 13:38:209200 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019201 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129202
9203 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019204 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129205
bnc691fda62016-08-12 00:43:169206 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529207 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589208 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:129209
[email protected]49639fa2011-12-20 23:22:419210 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:129211
bnc691fda62016-08-12 00:43:169212 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9213 callback2.callback());
robpercival214763f2016-07-01 23:27:019214 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129215
9216 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019217 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129218
bnc691fda62016-08-12 00:43:169219 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529220 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589221 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129222 }
9223
9224 // ------------------------------------------------------------------------
9225
9226 // Transaction 2: Request another resource in digestive's protection space.
9227 // This will preemptively add an Authorization header which should have an
9228 // "nc" value of 2 (as compared to 1 in the first use.
9229 {
[email protected]3c32c5f2010-05-18 15:18:129230 HttpRequestInfo request;
9231 request.method = "GET";
9232 // Note that Transaction 1 was at /x/y/z, so this is in the same
9233 // protection space as digest.
bncce36dca22015-04-21 22:11:239234 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109235 request.traffic_annotation =
9236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129237
bnc691fda62016-08-12 00:43:169238 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279239
[email protected]3c32c5f2010-05-18 15:18:129240 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239241 MockWrite(
9242 "GET /x/y/a/b HTTP/1.1\r\n"
9243 "Host: www.example.org\r\n"
9244 "Connection: keep-alive\r\n"
9245 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9246 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
9247 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
9248 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129249 };
9250
9251 // Sever accepts the authorization.
9252 MockRead data_reads1[] = {
9253 MockRead("HTTP/1.0 200 OK\r\n"),
9254 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069255 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129256 };
9257
Ryan Sleevib8d7ea02018-05-07 20:01:019258 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079259 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:129260
[email protected]49639fa2011-12-20 23:22:419261 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129262
tfarina42834112016-09-22 13:38:209263 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129265
9266 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019267 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129268
bnc691fda62016-08-12 00:43:169269 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529270 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589271 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129272 }
9273}
9274
[email protected]89ceba9a2009-03-21 03:46:069275// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:019276TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:069277 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:099278 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169279 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:069280
9281 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:449282 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:169283 trans.read_buf_len_ = 15;
9284 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:069285
9286 // Setup state in response_
bnc691fda62016-08-12 00:43:169287 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:589288 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:089289 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:579290 response->response_time = base::Time::Now();
9291 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:069292
9293 { // Setup state for response_.vary_data
9294 HttpRequestInfo request;
9295 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
9296 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:279297 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:439298 request.extra_headers.SetHeader("Foo", "1");
9299 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:509300 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:069301 }
9302
9303 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:169304 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:069305
9306 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:169307 EXPECT_FALSE(trans.read_buf_);
9308 EXPECT_EQ(0, trans.read_buf_len_);
9309 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:589310 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:529311 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:049312 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:089313 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:579314 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:069315}
9316
[email protected]bacff652009-03-31 17:50:339317// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:019318TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:339319 HttpRequestInfo request;
9320 request.method = "GET";
bncce36dca22015-04-21 22:11:239321 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109322 request.traffic_annotation =
9323 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339324
danakj1fd259a02016-04-16 03:17:099325 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169326 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279327
[email protected]bacff652009-03-31 17:50:339328 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239329 MockWrite(
9330 "GET / HTTP/1.1\r\n"
9331 "Host: www.example.org\r\n"
9332 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339333 };
9334
9335 MockRead data_reads[] = {
9336 MockRead("HTTP/1.0 200 OK\r\n"),
9337 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9338 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069339 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339340 };
9341
[email protected]5ecc992a42009-11-11 01:41:599342 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:019343 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069344 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9345 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339346
[email protected]bb88e1d32013-05-03 23:11:079347 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9348 session_deps_.socket_factory->AddSocketDataProvider(&data);
9349 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9350 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339351
[email protected]49639fa2011-12-20 23:22:419352 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339353
tfarina42834112016-09-22 13:38:209354 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019355 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339356
9357 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019358 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339359
bnc691fda62016-08-12 00:43:169360 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019361 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339362
9363 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019364 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339365
bnc691fda62016-08-12 00:43:169366 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339367
wezca1070932016-05-26 20:30:529368 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339369 EXPECT_EQ(100, response->headers->GetContentLength());
9370}
9371
9372// Test HTTPS connections to a site with a bad certificate, going through a
9373// proxy
bncd16676a2016-07-20 16:23:019374TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499375 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9376 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339377
9378 HttpRequestInfo request;
9379 request.method = "GET";
bncce36dca22015-04-21 22:11:239380 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109381 request.traffic_annotation =
9382 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339383
9384 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:179385 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9386 "Host: www.example.org:443\r\n"
9387 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339388 };
9389
9390 MockRead proxy_reads[] = {
9391 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069392 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:339393 };
9394
9395 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179396 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9397 "Host: www.example.org:443\r\n"
9398 "Proxy-Connection: keep-alive\r\n\r\n"),
9399 MockWrite("GET / HTTP/1.1\r\n"
9400 "Host: www.example.org\r\n"
9401 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339402 };
9403
9404 MockRead data_reads[] = {
9405 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9406 MockRead("HTTP/1.0 200 OK\r\n"),
9407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9408 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069409 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339410 };
9411
Ryan Sleevib8d7ea02018-05-07 20:01:019412 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
9413 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069414 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9415 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339416
[email protected]bb88e1d32013-05-03 23:11:079417 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9418 session_deps_.socket_factory->AddSocketDataProvider(&data);
9419 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9420 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339421
[email protected]49639fa2011-12-20 23:22:419422 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339423
9424 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:079425 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:339426
danakj1fd259a02016-04-16 03:17:099427 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169428 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:339429
tfarina42834112016-09-22 13:38:209430 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019431 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339432
9433 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019434 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339435
bnc691fda62016-08-12 00:43:169436 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019437 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339438
9439 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019440 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339441
bnc691fda62016-08-12 00:43:169442 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339443
wezca1070932016-05-26 20:30:529444 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339445 EXPECT_EQ(100, response->headers->GetContentLength());
9446 }
9447}
9448
[email protected]2df19bb2010-08-25 20:13:469449
9450// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:019451TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599452 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499453 ProxyResolutionService::CreateFixedFromPacResult(
9454 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519455 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079456 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:469457
9458 HttpRequestInfo request;
9459 request.method = "GET";
bncce36dca22015-04-21 22:11:239460 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109461 request.traffic_annotation =
9462 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:469463
9464 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179465 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9466 "Host: www.example.org:443\r\n"
9467 "Proxy-Connection: keep-alive\r\n\r\n"),
9468 MockWrite("GET / HTTP/1.1\r\n"
9469 "Host: www.example.org\r\n"
9470 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:469471 };
9472
9473 MockRead data_reads[] = {
9474 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9475 MockRead("HTTP/1.1 200 OK\r\n"),
9476 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9477 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069478 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:469479 };
9480
Ryan Sleevib8d7ea02018-05-07 20:01:019481 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069482 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9483 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:469484
[email protected]bb88e1d32013-05-03 23:11:079485 session_deps_.socket_factory->AddSocketDataProvider(&data);
9486 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9487 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:469488
[email protected]49639fa2011-12-20 23:22:419489 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:469490
danakj1fd259a02016-04-16 03:17:099491 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169492 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:469493
tfarina42834112016-09-22 13:38:209494 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019495 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:469496
9497 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019498 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169499 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:469500
wezca1070932016-05-26 20:30:529501 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:469502
tbansal2ecbbc72016-10-06 17:15:479503 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:469504 EXPECT_TRUE(response->headers->IsKeepAlive());
9505 EXPECT_EQ(200, response->headers->response_code());
9506 EXPECT_EQ(100, response->headers->GetContentLength());
9507 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:209508
9509 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:169510 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:209511 TestLoadTimingNotReusedWithPac(load_timing_info,
9512 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:469513}
9514
Eric Roman695a7872019-04-16 21:53:299515// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:019516TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599517 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499518 ProxyResolutionService::CreateFixedFromPacResult(
9519 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519520 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079521 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:299522
Matt Menkeecfecfc72019-02-05 19:15:289523 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9524 session_deps_.host_resolver->set_ondemand_mode(true);
9525
[email protected]511f6f52010-12-17 03:58:299526 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:129527 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:299528 request.method = "GET";
bncce36dca22015-04-21 22:11:239529 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109530 request.traffic_annotation =
9531 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299532
9533 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:289534 MockWrite(ASYNC, 0,
9535 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:179536 "Host: www.example.org:443\r\n"
9537 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299538 };
9539
9540 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289541 // Pause on first read.
9542 MockRead(ASYNC, ERR_IO_PENDING, 1),
9543 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
9544 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
9545 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299546 };
9547
Matt Menkeecfecfc72019-02-05 19:15:289548 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069549 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299550
[email protected]bb88e1d32013-05-03 23:11:079551 session_deps_.socket_factory->AddSocketDataProvider(&data);
9552 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299553
[email protected]49639fa2011-12-20 23:22:419554 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299555
danakj1fd259a02016-04-16 03:17:099556 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169557 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299558
tfarina42834112016-09-22 13:38:209559 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019560 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289561 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
9562
9563 // Host resolution takes |kTimeIncrement|.
9564 FastForwardBy(kTimeIncrement);
9565 // Resolving the current request with |ResolveNow| will cause the pending
9566 // request to instantly complete, and the async connect will start as well.
9567 session_deps_.host_resolver->ResolveOnlyRequestNow();
9568
9569 // Connecting takes |kTimeIncrement|.
9570 FastForwardBy(kTimeIncrement);
9571 data.RunUntilPaused();
9572
9573 // The server takes |kTimeIncrement| to respond.
9574 FastForwardBy(kTimeIncrement);
9575 data.Resume();
[email protected]511f6f52010-12-17 03:58:299576
9577 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599578 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299579}
9580
Eric Roman74103c72019-02-21 00:23:129581// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
9582TEST_F(HttpNetworkTransactionTest,
9583 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
9584 base::HistogramTester histograms;
9585 session_deps_.proxy_resolution_service =
9586 ProxyResolutionService::CreateFixedFromPacResult(
9587 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9588 TestNetLog net_log;
9589 session_deps_.net_log = &net_log;
9590
9591 HttpRequestInfo request;
9592 request.method = "GET";
9593 request.url = GURL("https://www.example.org/");
9594 request.traffic_annotation =
9595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9596
9597 MockWrite data_writes[] = {
9598 MockWrite(ASYNC, 0,
9599 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9600 "Host: www.example.org:443\r\n"
9601 "Proxy-Connection: keep-alive\r\n\r\n"),
9602 };
9603
9604 MockRead data_reads[] = {
9605 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9606 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9607 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9608 };
9609
9610 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9611 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9612
9613 session_deps_.socket_factory->AddSocketDataProvider(&data);
9614 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9615
9616 TestCompletionCallback callback;
9617
9618 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9619 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9620
9621 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9622 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9623
9624 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599625 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129626}
9627
9628// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
9629// request for main frames.
9630TEST_F(HttpNetworkTransactionTest,
9631 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
9632 base::HistogramTester histograms;
9633 session_deps_.proxy_resolution_service =
9634 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
9635 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9636 TestNetLog net_log;
9637 session_deps_.net_log = &net_log;
9638
9639 HttpRequestInfo request;
9640 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
9641 request.method = "GET";
9642 request.url = GURL("https://www.example.org/");
9643 request.traffic_annotation =
9644 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9645
9646 MockWrite data_writes[] = {
9647 MockWrite(ASYNC, 0,
9648 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9649 "Host: www.example.org:443\r\n"
9650 "Proxy-Connection: keep-alive\r\n\r\n"),
9651 };
9652
9653 MockRead data_reads[] = {
9654 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9655 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9656 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9657 };
9658
9659 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9660 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9661
9662 session_deps_.socket_factory->AddSocketDataProvider(&data);
9663 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9664
9665 TestCompletionCallback callback;
9666
9667 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9668 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9669
9670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9672
9673 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599674 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129675}
9676
Eric Roman695a7872019-04-16 21:53:299677// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:129678// frames.
bncd16676a2016-07-20 16:23:019679TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:129680 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:499681 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9682 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:289683 TestNetLog net_log;
9684 session_deps_.net_log = &net_log;
9685
Matt Menkeecfecfc72019-02-05 19:15:289686 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9687 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:299688
9689 HttpRequestInfo request;
9690 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:129691 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:239692 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109693 request.traffic_annotation =
9694 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299695
Ryan Hamilton0239aac2018-05-19 00:03:139696 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049697 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9698 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139699 spdy::SpdySerializedFrame goaway(
9700 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299701 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419702 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:289703 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:299704 };
9705
9706 static const char* const kExtraHeaders[] = {
9707 "location",
9708 "http://login.example.com/",
9709 };
Ryan Hamilton0239aac2018-05-19 00:03:139710 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249711 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:299712 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289713 // Pause on first read.
9714 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
9715 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299716 };
9717
Matt Menkeecfecfc72019-02-05 19:15:289718 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069719 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369720 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299721
[email protected]bb88e1d32013-05-03 23:11:079722 session_deps_.socket_factory->AddSocketDataProvider(&data);
9723 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299724
[email protected]49639fa2011-12-20 23:22:419725 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299726
danakj1fd259a02016-04-16 03:17:099727 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169728 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299729
tfarina42834112016-09-22 13:38:209730 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019731 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289732 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:299733
Matt Menkeecfecfc72019-02-05 19:15:289734 // Host resolution takes |kTimeIncrement|.
9735 FastForwardBy(kTimeIncrement);
9736 // Resolving the current request with |ResolveNow| will cause the pending
9737 // request to instantly complete, and the async connect will start as well.
9738 session_deps_.host_resolver->ResolveOnlyRequestNow();
9739
9740 // Connecting takes |kTimeIncrement|.
9741 FastForwardBy(kTimeIncrement);
9742 data.RunUntilPaused();
9743
9744 FastForwardBy(kTimeIncrement);
9745 data.Resume();
[email protected]511f6f52010-12-17 03:58:299746 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599747 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299748}
9749
[email protected]4eddbc732012-08-09 05:40:179750// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019751TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499752 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9753 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299754
9755 HttpRequestInfo request;
9756 request.method = "GET";
bncce36dca22015-04-21 22:11:239757 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109758 request.traffic_annotation =
9759 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299760
9761 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179762 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9763 "Host: www.example.org:443\r\n"
9764 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299765 };
9766
9767 MockRead data_reads[] = {
9768 MockRead("HTTP/1.1 404 Not Found\r\n"),
9769 MockRead("Content-Length: 23\r\n\r\n"),
9770 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:069771 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:299772 };
9773
Ryan Sleevib8d7ea02018-05-07 20:01:019774 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069775 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299776
[email protected]bb88e1d32013-05-03 23:11:079777 session_deps_.socket_factory->AddSocketDataProvider(&data);
9778 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299779
[email protected]49639fa2011-12-20 23:22:419780 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299781
danakj1fd259a02016-04-16 03:17:099782 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169783 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299784
tfarina42834112016-09-22 13:38:209785 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019786 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299787
9788 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019789 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299790
ttuttle960fcbf2016-04-19 13:26:329791 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299792}
9793
[email protected]4eddbc732012-08-09 05:40:179794// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019795TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499796 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9797 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299798
9799 HttpRequestInfo request;
9800 request.method = "GET";
bncce36dca22015-04-21 22:11:239801 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109802 request.traffic_annotation =
9803 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299804
Ryan Hamilton0239aac2018-05-19 00:03:139805 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049806 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9807 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139808 spdy::SpdySerializedFrame rst(
9809 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299810 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419811 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:299812 };
9813
9814 static const char* const kExtraHeaders[] = {
9815 "location",
9816 "http://login.example.com/",
9817 };
Ryan Hamilton0239aac2018-05-19 00:03:139818 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249819 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:139820 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:199821 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:299822 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:419823 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:139824 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299825 };
9826
Ryan Sleevib8d7ea02018-05-07 20:01:019827 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069828 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369829 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299830
[email protected]bb88e1d32013-05-03 23:11:079831 session_deps_.socket_factory->AddSocketDataProvider(&data);
9832 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299833
[email protected]49639fa2011-12-20 23:22:419834 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299835
danakj1fd259a02016-04-16 03:17:099836 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169837 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299838
tfarina42834112016-09-22 13:38:209839 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019840 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299841
9842 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019843 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299844
ttuttle960fcbf2016-04-19 13:26:329845 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299846}
9847
[email protected]0c5fb722012-02-28 11:50:359848// Test the request-challenge-retry sequence for basic auth, through
9849// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:019850TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:359851 HttpRequestInfo request;
9852 request.method = "GET";
bncce36dca22015-04-21 22:11:239853 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:359854 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:299855 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:109856 request.traffic_annotation =
9857 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:359858
9859 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:599860 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499861 ProxyResolutionService::CreateFixedFromPacResult(
9862 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519863 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:079864 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:099865 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:359866
9867 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:139868 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049869 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9870 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139871 spdy::SpdySerializedFrame rst(
9872 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:389873 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:359874
bnc691fda62016-08-12 00:43:169875 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:359876 // be issuing -- the final header line contains the credentials.
9877 const char* const kAuthCredentials[] = {
9878 "proxy-authorization", "Basic Zm9vOmJhcg==",
9879 };
Ryan Hamilton0239aac2018-05-19 00:03:139880 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049881 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
9882 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:239883 HostPortPair("www.example.org", 443)));
9884 // fetch https://www.example.org/ via HTTP
9885 const char get[] =
9886 "GET / HTTP/1.1\r\n"
9887 "Host: www.example.org\r\n"
9888 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:139889 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:199890 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:359891
9892 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:419893 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
9894 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:359895 };
9896
9897 // The proxy responds to the connect with a 407, using a persistent
9898 // connection.
thestig9d3bb0c2015-01-24 00:49:519899 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:359900 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:359901 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
9902 };
Ryan Hamilton0239aac2018-05-19 00:03:139903 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249904 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:359905
Ryan Hamilton0239aac2018-05-19 00:03:139906 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:359907 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:359908 const char resp[] = "HTTP/1.1 200 OK\r\n"
9909 "Content-Length: 5\r\n\r\n";
9910
Ryan Hamilton0239aac2018-05-19 00:03:139911 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:199912 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:139913 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:199914 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:359915 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:419916 CreateMockRead(conn_auth_resp, 1, ASYNC),
9917 CreateMockRead(conn_resp, 4, ASYNC),
9918 CreateMockRead(wrapped_get_resp, 6, ASYNC),
9919 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:139920 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:359921 };
9922
Ryan Sleevib8d7ea02018-05-07 20:01:019923 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:079924 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:359925 // Negotiate SPDY to the proxy
9926 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:369927 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:079928 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:359929 // Vanilla SSL to the server
9930 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079931 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:359932
9933 TestCompletionCallback callback1;
9934
bnc87dcefc2017-05-25 12:47:589935 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199936 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:359937
9938 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:019939 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359940
9941 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019942 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:469943 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:359944 log.GetEntries(&entries);
9945 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:009946 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9947 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359948 ExpectLogContainsSomewhere(
9949 entries, pos,
mikecirone8b85c432016-09-08 19:11:009950 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9951 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359952
9953 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529954 ASSERT_TRUE(response);
9955 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:359956 EXPECT_EQ(407, response->headers->response_code());
9957 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:589958 EXPECT_TRUE(response->auth_challenge.has_value());
9959 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:359960
9961 TestCompletionCallback callback2;
9962
9963 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
9964 callback2.callback());
robpercival214763f2016-07-01 23:27:019965 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359966
9967 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019968 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:359969
9970 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529971 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:359972
9973 EXPECT_TRUE(response->headers->IsKeepAlive());
9974 EXPECT_EQ(200, response->headers->response_code());
9975 EXPECT_EQ(5, response->headers->GetContentLength());
9976 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9977
9978 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:589979 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:359980
[email protected]029c83b62013-01-24 05:28:209981 LoadTimingInfo load_timing_info;
9982 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9983 TestLoadTimingNotReusedWithPac(load_timing_info,
9984 CONNECT_TIMING_HAS_SSL_TIMES);
9985
[email protected]0c5fb722012-02-28 11:50:359986 trans.reset();
9987 session->CloseAllConnections();
9988}
9989
[email protected]7c6f7ba2012-04-03 04:09:299990// Test that an explicitly trusted SPDY proxy can push a resource from an
9991// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:019992TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:159993 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:199994 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:159995 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
9996 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:299997 HttpRequestInfo request;
9998 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:109999 request.traffic_annotation =
10000 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910001
[email protected]7c6f7ba2012-04-03 04:09:2910002 request.method = "GET";
bncce36dca22015-04-21 22:11:2310003 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910004 push_request.method = "GET";
10005 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1010006 push_request.traffic_annotation =
10007 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910008
tbansal28e68f82016-02-04 02:56:1510009 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910010 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910011 ProxyResolutionService::CreateFixedFromPacResult(
10012 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110013 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710014 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010015
Eric Roman3d8546a2018-09-10 17:00:5210016 session_deps_.proxy_resolution_service->SetProxyDelegate(
10017 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010018
danakj1fd259a02016-04-16 03:17:0910019 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910020
Ryan Hamilton0239aac2018-05-19 00:03:1310021 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510022 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310023 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510024 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910025
10026 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110027 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510028 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910029 };
10030
Ryan Hamilton0239aac2018-05-19 00:03:1310031 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510032 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610033
Ryan Hamilton0239aac2018-05-19 00:03:1310034 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510035 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910036
Ryan Hamilton0239aac2018-05-19 00:03:1310037 spdy::SpdySerializedFrame stream1_body(
10038 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910039
Ryan Hamilton0239aac2018-05-19 00:03:1310040 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910041 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910042
10043 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610044 CreateMockRead(stream2_syn, 1, ASYNC),
10045 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510046 CreateMockRead(stream1_body, 4, ASYNC),
10047 CreateMockRead(stream2_body, 5, ASYNC),
10048 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910049 };
10050
Ryan Sleevib8d7ea02018-05-07 20:01:0110051 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710052 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910053 // Negotiate SPDY to the proxy
10054 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610055 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710056 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910057
bnc87dcefc2017-05-25 12:47:5810058 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910059 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910060 TestCompletionCallback callback;
10061 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110062 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910063
10064 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110065 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910066 const HttpResponseInfo* response = trans->GetResponseInfo();
10067
bnc87dcefc2017-05-25 12:47:5810068 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910069 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010070 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110071 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910072
10073 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110074 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910075 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10076
wezca1070932016-05-26 20:30:5210077 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910078 EXPECT_TRUE(response->headers->IsKeepAlive());
10079
10080 EXPECT_EQ(200, response->headers->response_code());
10081 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10082
10083 std::string response_data;
10084 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110085 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910086 EXPECT_EQ("hello!", response_data);
10087
[email protected]029c83b62013-01-24 05:28:2010088 LoadTimingInfo load_timing_info;
10089 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10090 TestLoadTimingNotReusedWithPac(load_timing_info,
10091 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10092
[email protected]7c6f7ba2012-04-03 04:09:2910093 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210094 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910095 EXPECT_EQ(200, push_response->headers->response_code());
10096
10097 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110098 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910099 EXPECT_EQ("pushed", response_data);
10100
[email protected]029c83b62013-01-24 05:28:2010101 LoadTimingInfo push_load_timing_info;
10102 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10103 TestLoadTimingReusedWithPac(push_load_timing_info);
10104 // The transactions should share a socket ID, despite being for different
10105 // origins.
10106 EXPECT_EQ(load_timing_info.socket_log_id,
10107 push_load_timing_info.socket_log_id);
10108
[email protected]7c6f7ba2012-04-03 04:09:2910109 trans.reset();
10110 push_trans.reset();
10111 session->CloseAllConnections();
10112}
10113
[email protected]8c843192012-04-05 07:15:0010114// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110115TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510116 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910117 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510118 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10119 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010120 HttpRequestInfo request;
10121
10122 request.method = "GET";
bncce36dca22015-04-21 22:11:2310123 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010124 request.traffic_annotation =
10125 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010126
Ramin Halavatica8d5252018-03-12 05:33:4910127 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10128 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110129 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710130 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010131
10132 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210133 session_deps_.proxy_resolution_service->SetProxyDelegate(
10134 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010135
danakj1fd259a02016-04-16 03:17:0910136 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010137
Ryan Hamilton0239aac2018-05-19 00:03:1310138 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510139 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010140
Ryan Hamilton0239aac2018-05-19 00:03:1310141 spdy::SpdySerializedFrame push_rst(
10142 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010143
10144 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110145 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0010146 };
10147
Ryan Hamilton0239aac2018-05-19 00:03:1310148 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510149 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0010150
Ryan Hamilton0239aac2018-05-19 00:03:1310151 spdy::SpdySerializedFrame stream1_body(
10152 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0010153
Ryan Hamilton0239aac2018-05-19 00:03:1310154 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510155 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0010156
10157 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110158 CreateMockRead(stream1_reply, 1, ASYNC),
10159 CreateMockRead(stream2_syn, 2, ASYNC),
10160 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5910161 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0010162 };
10163
Ryan Sleevib8d7ea02018-05-07 20:01:0110164 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710165 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0010166 // Negotiate SPDY to the proxy
10167 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610168 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710169 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0010170
bnc87dcefc2017-05-25 12:47:5810171 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910172 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0010173 TestCompletionCallback callback;
10174 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110175 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0010176
10177 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110178 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010179 const HttpResponseInfo* response = trans->GetResponseInfo();
10180
wezca1070932016-05-26 20:30:5210181 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0010182 EXPECT_TRUE(response->headers->IsKeepAlive());
10183
10184 EXPECT_EQ(200, response->headers->response_code());
10185 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10186
10187 std::string response_data;
10188 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110189 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010190 EXPECT_EQ("hello!", response_data);
10191
10192 trans.reset();
10193 session->CloseAllConnections();
10194}
10195
tbansal8ef1d3e2016-02-03 04:05:4210196// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
10197// resources.
bncd16676a2016-07-20 16:23:0110198TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510199 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910200 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510201 proxy_delegate->set_trusted_spdy_proxy(
10202 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
10203
tbansal8ef1d3e2016-02-03 04:05:4210204 HttpRequestInfo request;
10205
10206 request.method = "GET";
10207 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010208 request.traffic_annotation =
10209 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210210
10211 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4910212 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10213 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210214 BoundTestNetLog log;
10215 session_deps_.net_log = log.bound().net_log();
10216
10217 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210218 session_deps_.proxy_resolution_service->SetProxyDelegate(
10219 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4210220
danakj1fd259a02016-04-16 03:17:0910221 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4210222
Ryan Hamilton0239aac2018-05-19 00:03:1310223 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510224 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310225 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510226 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4210227
10228 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110229 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510230 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4210231 };
10232
Ryan Hamilton0239aac2018-05-19 00:03:1310233 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1510234 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210235
Ryan Hamilton0239aac2018-05-19 00:03:1310236 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3310237 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4910238
Ryan Hamilton0239aac2018-05-19 00:03:1310239 spdy::SpdySerializedFrame stream1_body(
10240 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210241
Ryan Hamilton0239aac2018-05-19 00:03:1310242 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1510243 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210244
Ryan Hamilton0239aac2018-05-19 00:03:1310245 spdy::SpdySerializedFrame stream2_body(
10246 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210247
10248 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110249 CreateMockRead(stream1_reply, 1, ASYNC),
10250 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510251 CreateMockRead(stream1_body, 4, ASYNC),
10252 CreateMockRead(stream2_body, 5, ASYNC),
10253 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4210254 };
10255
Ryan Sleevib8d7ea02018-05-07 20:01:0110256 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4210257 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10258 // Negotiate SPDY to the proxy
10259 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610260 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4210261 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
10262
bnc87dcefc2017-05-25 12:47:5810263 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910264 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4210265 TestCompletionCallback callback;
10266 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110267 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4210268
10269 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110270 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210271 const HttpResponseInfo* response = trans->GetResponseInfo();
10272
wezca1070932016-05-26 20:30:5210273 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4210274 EXPECT_TRUE(response->headers->IsKeepAlive());
10275
10276 EXPECT_EQ(200, response->headers->response_code());
10277 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10278
10279 std::string response_data;
10280 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110281 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210282 EXPECT_EQ("hello!", response_data);
10283
10284 trans.reset();
10285 session->CloseAllConnections();
10286}
10287
[email protected]2df19bb2010-08-25 20:13:4610288// Test HTTPS connections to a site with a bad certificate, going through an
10289// HTTPS proxy
bncd16676a2016-07-20 16:23:0110290TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910291 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10292 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610293
10294 HttpRequestInfo request;
10295 request.method = "GET";
bncce36dca22015-04-21 22:11:2310296 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010297 request.traffic_annotation =
10298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610299
10300 // Attempt to fetch the URL from a server with a bad cert
10301 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710302 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10303 "Host: www.example.org:443\r\n"
10304 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610305 };
10306
10307 MockRead bad_cert_reads[] = {
10308 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610309 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4610310 };
10311
10312 // Attempt to fetch the URL with a good cert
10313 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710314 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10315 "Host: www.example.org:443\r\n"
10316 "Proxy-Connection: keep-alive\r\n\r\n"),
10317 MockWrite("GET / HTTP/1.1\r\n"
10318 "Host: www.example.org\r\n"
10319 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610320 };
10321
10322 MockRead good_cert_reads[] = {
10323 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10324 MockRead("HTTP/1.0 200 OK\r\n"),
10325 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10326 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610327 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610328 };
10329
Ryan Sleevib8d7ea02018-05-07 20:01:0110330 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
10331 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0610332 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10333 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4610334
10335 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0710336 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10337 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10338 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4610339
10340 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0710341 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10342 session_deps_.socket_factory->AddSocketDataProvider(&data);
10343 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4610344
[email protected]49639fa2011-12-20 23:22:4110345 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610346
danakj1fd259a02016-04-16 03:17:0910347 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610348 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610349
tfarina42834112016-09-22 13:38:2010350 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110351 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610352
10353 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110354 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4610355
bnc691fda62016-08-12 00:43:1610356 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110357 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610358
10359 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110360 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4610361
bnc691fda62016-08-12 00:43:1610362 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610363
wezca1070932016-05-26 20:30:5210364 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610365 EXPECT_EQ(100, response->headers->GetContentLength());
10366}
10367
bncd16676a2016-07-20 16:23:0110368TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4210369 HttpRequestInfo request;
10370 request.method = "GET";
bncce36dca22015-04-21 22:11:2310371 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310372 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10373 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1010374 request.traffic_annotation =
10375 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210376
danakj1fd259a02016-04-16 03:17:0910377 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610378 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710379
[email protected]1c773ea12009-04-28 19:58:4210380 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310381 MockWrite(
10382 "GET / HTTP/1.1\r\n"
10383 "Host: www.example.org\r\n"
10384 "Connection: keep-alive\r\n"
10385 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210386 };
10387
10388 // Lastly, the server responds with the actual content.
10389 MockRead data_reads[] = {
10390 MockRead("HTTP/1.0 200 OK\r\n"),
10391 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10392 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610393 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210394 };
10395
Ryan Sleevib8d7ea02018-05-07 20:01:0110396 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710397 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210398
[email protected]49639fa2011-12-20 23:22:4110399 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210400
tfarina42834112016-09-22 13:38:2010401 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110402 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210403
10404 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110405 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210406}
10407
bncd16676a2016-07-20 16:23:0110408TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0010409 // Test user agent values, used both for the request header of the original
10410 // request, and the value returned by the HttpUserAgentSettings. nullptr means
10411 // no request header / no HttpUserAgentSettings object.
10412 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2910413
Matt Menked732ea42019-03-08 12:05:0010414 for (const char* setting_user_agent : kTestUserAgents) {
10415 if (!setting_user_agent) {
10416 session_deps_.http_user_agent_settings.reset();
10417 } else {
10418 session_deps_.http_user_agent_settings =
10419 std::make_unique<StaticHttpUserAgentSettings>(
10420 std::string() /* accept-language */, setting_user_agent);
10421 }
10422 session_deps_.proxy_resolution_service =
10423 ProxyResolutionService::CreateFixed("myproxy:70",
10424 TRAFFIC_ANNOTATION_FOR_TESTS);
10425 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10426 for (const char* request_user_agent : kTestUserAgents) {
10427 HttpRequestInfo request;
10428 request.method = "GET";
10429 request.url = GURL("https://www.example.org/");
10430 if (request_user_agent) {
10431 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10432 request_user_agent);
10433 }
10434 request.traffic_annotation =
10435 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710436
Matt Menked732ea42019-03-08 12:05:0010437 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2910438
Matt Menked732ea42019-03-08 12:05:0010439 std::string expected_request;
10440 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
10441 expected_request =
10442 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10443 "Host: www.example.org:443\r\n"
10444 "Proxy-Connection: keep-alive\r\n\r\n";
10445 } else {
10446 expected_request = base::StringPrintf(
10447 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10448 "Host: www.example.org:443\r\n"
10449 "Proxy-Connection: keep-alive\r\n"
10450 "User-Agent: %s\r\n\r\n",
10451 setting_user_agent);
10452 }
10453 MockWrite data_writes[] = {
10454 MockWrite(expected_request.c_str()),
10455 };
10456 MockRead data_reads[] = {
10457 // Return an error, so the transaction stops here (this test isn't
10458 // interested in the rest).
10459 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10460 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10461 MockRead("Proxy-Connection: close\r\n\r\n"),
10462 };
[email protected]da81f132010-08-18 23:39:2910463
Matt Menked732ea42019-03-08 12:05:0010464 StaticSocketDataProvider data(data_reads, data_writes);
10465 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2910466
Matt Menked732ea42019-03-08 12:05:0010467 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2910468
Matt Menked732ea42019-03-08 12:05:0010469 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10470 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10471
10472 rv = callback.WaitForResult();
10473 EXPECT_THAT(rv, IsOk());
10474 }
10475 }
[email protected]da81f132010-08-18 23:39:2910476}
10477
bncd16676a2016-07-20 16:23:0110478TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4210479 HttpRequestInfo request;
10480 request.method = "GET";
bncce36dca22015-04-21 22:11:2310481 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1610482 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
10483 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1010484 request.traffic_annotation =
10485 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210486
danakj1fd259a02016-04-16 03:17:0910487 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610488 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710489
[email protected]1c773ea12009-04-28 19:58:4210490 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310491 MockWrite(
10492 "GET / HTTP/1.1\r\n"
10493 "Host: www.example.org\r\n"
10494 "Connection: keep-alive\r\n"
10495 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210496 };
10497
10498 // Lastly, the server responds with the actual content.
10499 MockRead data_reads[] = {
10500 MockRead("HTTP/1.0 200 OK\r\n"),
10501 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10502 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610503 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210504 };
10505
Ryan Sleevib8d7ea02018-05-07 20:01:0110506 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710507 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210508
[email protected]49639fa2011-12-20 23:22:4110509 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210510
tfarina42834112016-09-22 13:38:2010511 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110512 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210513
10514 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110515 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210516}
10517
bncd16676a2016-07-20 16:23:0110518TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210519 HttpRequestInfo request;
10520 request.method = "POST";
bncce36dca22015-04-21 22:11:2310521 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010522 request.traffic_annotation =
10523 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210524
danakj1fd259a02016-04-16 03:17:0910525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610526 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710527
[email protected]1c773ea12009-04-28 19:58:4210528 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310529 MockWrite(
10530 "POST / HTTP/1.1\r\n"
10531 "Host: www.example.org\r\n"
10532 "Connection: keep-alive\r\n"
10533 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210534 };
10535
10536 // Lastly, the server responds with the actual content.
10537 MockRead data_reads[] = {
10538 MockRead("HTTP/1.0 200 OK\r\n"),
10539 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10540 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610541 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210542 };
10543
Ryan Sleevib8d7ea02018-05-07 20:01:0110544 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710545 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210546
[email protected]49639fa2011-12-20 23:22:4110547 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210548
tfarina42834112016-09-22 13:38:2010549 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110550 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210551
10552 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110553 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210554}
10555
bncd16676a2016-07-20 16:23:0110556TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210557 HttpRequestInfo request;
10558 request.method = "PUT";
bncce36dca22015-04-21 22:11:2310559 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010560 request.traffic_annotation =
10561 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210562
danakj1fd259a02016-04-16 03:17:0910563 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610564 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710565
[email protected]1c773ea12009-04-28 19:58:4210566 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310567 MockWrite(
10568 "PUT / HTTP/1.1\r\n"
10569 "Host: www.example.org\r\n"
10570 "Connection: keep-alive\r\n"
10571 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210572 };
10573
10574 // Lastly, the server responds with the actual content.
10575 MockRead data_reads[] = {
10576 MockRead("HTTP/1.0 200 OK\r\n"),
10577 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10578 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610579 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210580 };
10581
Ryan Sleevib8d7ea02018-05-07 20:01:0110582 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710583 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210584
[email protected]49639fa2011-12-20 23:22:4110585 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210586
tfarina42834112016-09-22 13:38:2010587 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110588 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210589
10590 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110591 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210592}
10593
bncd16676a2016-07-20 16:23:0110594TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210595 HttpRequestInfo request;
10596 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2310597 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010598 request.traffic_annotation =
10599 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210600
danakj1fd259a02016-04-16 03:17:0910601 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610602 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710603
[email protected]1c773ea12009-04-28 19:58:4210604 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1310605 MockWrite("HEAD / HTTP/1.1\r\n"
10606 "Host: www.example.org\r\n"
10607 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210608 };
10609
10610 // Lastly, the server responds with the actual content.
10611 MockRead data_reads[] = {
10612 MockRead("HTTP/1.0 200 OK\r\n"),
10613 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10614 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610615 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210616 };
10617
Ryan Sleevib8d7ea02018-05-07 20:01:0110618 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710619 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210620
[email protected]49639fa2011-12-20 23:22:4110621 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210622
tfarina42834112016-09-22 13:38:2010623 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110624 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210625
10626 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110627 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210628}
10629
bncd16676a2016-07-20 16:23:0110630TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4210631 HttpRequestInfo request;
10632 request.method = "GET";
bncce36dca22015-04-21 22:11:2310633 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210634 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010635 request.traffic_annotation =
10636 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210637
danakj1fd259a02016-04-16 03:17:0910638 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610639 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710640
[email protected]1c773ea12009-04-28 19:58:4210641 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310642 MockWrite(
10643 "GET / HTTP/1.1\r\n"
10644 "Host: www.example.org\r\n"
10645 "Connection: keep-alive\r\n"
10646 "Pragma: no-cache\r\n"
10647 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210648 };
10649
10650 // Lastly, the server responds with the actual content.
10651 MockRead data_reads[] = {
10652 MockRead("HTTP/1.0 200 OK\r\n"),
10653 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10654 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610655 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210656 };
10657
Ryan Sleevib8d7ea02018-05-07 20:01:0110658 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710659 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210660
[email protected]49639fa2011-12-20 23:22:4110661 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210662
tfarina42834112016-09-22 13:38:2010663 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110664 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210665
10666 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110667 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210668}
10669
bncd16676a2016-07-20 16:23:0110670TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4210671 HttpRequestInfo request;
10672 request.method = "GET";
bncce36dca22015-04-21 22:11:2310673 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210674 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010675 request.traffic_annotation =
10676 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210677
danakj1fd259a02016-04-16 03:17:0910678 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610679 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710680
[email protected]1c773ea12009-04-28 19:58:4210681 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310682 MockWrite(
10683 "GET / HTTP/1.1\r\n"
10684 "Host: www.example.org\r\n"
10685 "Connection: keep-alive\r\n"
10686 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210687 };
10688
10689 // Lastly, the server responds with the actual content.
10690 MockRead data_reads[] = {
10691 MockRead("HTTP/1.0 200 OK\r\n"),
10692 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10693 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610694 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210695 };
10696
Ryan Sleevib8d7ea02018-05-07 20:01:0110697 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710698 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210699
[email protected]49639fa2011-12-20 23:22:4110700 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210701
tfarina42834112016-09-22 13:38:2010702 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110703 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210704
10705 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110706 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210707}
10708
bncd16676a2016-07-20 16:23:0110709TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4210710 HttpRequestInfo request;
10711 request.method = "GET";
bncce36dca22015-04-21 22:11:2310712 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310713 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010714 request.traffic_annotation =
10715 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210716
danakj1fd259a02016-04-16 03:17:0910717 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610718 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710719
[email protected]1c773ea12009-04-28 19:58:4210720 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310721 MockWrite(
10722 "GET / HTTP/1.1\r\n"
10723 "Host: www.example.org\r\n"
10724 "Connection: keep-alive\r\n"
10725 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210726 };
10727
10728 // Lastly, the server responds with the actual content.
10729 MockRead data_reads[] = {
10730 MockRead("HTTP/1.0 200 OK\r\n"),
10731 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10732 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610733 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210734 };
10735
Ryan Sleevib8d7ea02018-05-07 20:01:0110736 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710737 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210738
[email protected]49639fa2011-12-20 23:22:4110739 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210740
tfarina42834112016-09-22 13:38:2010741 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110742 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210743
10744 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110745 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210746}
10747
bncd16676a2016-07-20 16:23:0110748TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4710749 HttpRequestInfo request;
10750 request.method = "GET";
bncce36dca22015-04-21 22:11:2310751 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310752 request.extra_headers.SetHeader("referer", "www.foo.com");
10753 request.extra_headers.SetHeader("hEllo", "Kitty");
10754 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010755 request.traffic_annotation =
10756 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4710757
danakj1fd259a02016-04-16 03:17:0910758 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610759 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710760
[email protected]270c6412010-03-29 22:02:4710761 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310762 MockWrite(
10763 "GET / HTTP/1.1\r\n"
10764 "Host: www.example.org\r\n"
10765 "Connection: keep-alive\r\n"
10766 "referer: www.foo.com\r\n"
10767 "hEllo: Kitty\r\n"
10768 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4710769 };
10770
10771 // Lastly, the server responds with the actual content.
10772 MockRead data_reads[] = {
10773 MockRead("HTTP/1.0 200 OK\r\n"),
10774 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10775 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610776 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4710777 };
10778
Ryan Sleevib8d7ea02018-05-07 20:01:0110779 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710780 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4710781
[email protected]49639fa2011-12-20 23:22:4110782 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4710783
tfarina42834112016-09-22 13:38:2010784 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110785 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4710786
10787 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110788 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4710789}
10790
bncd16676a2016-07-20 16:23:0110791TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710792 HttpRequestInfo request;
10793 request.method = "GET";
bncce36dca22015-04-21 22:11:2310794 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010795 request.traffic_annotation =
10796 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710797
Lily Houghton8c2f97d2018-01-22 05:06:5910798 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910799 ProxyResolutionService::CreateFixedFromPacResult(
10800 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110801 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710802 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210803
danakj1fd259a02016-04-16 03:17:0910804 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610805 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210806
[email protected]3cd17242009-06-23 02:59:0210807 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10808 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10809
10810 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410811 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10812 MockWrite("GET / HTTP/1.1\r\n"
10813 "Host: www.example.org\r\n"
10814 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210815
10816 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410817 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10818 MockRead("HTTP/1.0 200 OK\r\n"),
10819 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10820 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0210821
Ryan Sleevib8d7ea02018-05-07 20:01:0110822 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710823 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0210824
[email protected]49639fa2011-12-20 23:22:4110825 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0210826
tfarina42834112016-09-22 13:38:2010827 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110828 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0210829
10830 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110831 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210832
bnc691fda62016-08-12 00:43:1610833 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210834 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0210835
tbansal2ecbbc72016-10-06 17:15:4710836 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2010837 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610838 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010839 TestLoadTimingNotReusedWithPac(load_timing_info,
10840 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10841
[email protected]3cd17242009-06-23 02:59:0210842 std::string response_text;
bnc691fda62016-08-12 00:43:1610843 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110844 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210845 EXPECT_EQ("Payload", response_text);
10846}
10847
bncd16676a2016-07-20 16:23:0110848TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710849 HttpRequestInfo request;
10850 request.method = "GET";
bncce36dca22015-04-21 22:11:2310851 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010852 request.traffic_annotation =
10853 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710854
Lily Houghton8c2f97d2018-01-22 05:06:5910855 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910856 ProxyResolutionService::CreateFixedFromPacResult(
10857 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110858 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710859 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210860
danakj1fd259a02016-04-16 03:17:0910861 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610862 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210863
[email protected]3cd17242009-06-23 02:59:0210864 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
10865 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10866
10867 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310868 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2410869 base::size(write_buffer)),
10870 MockWrite("GET / HTTP/1.1\r\n"
10871 "Host: www.example.org\r\n"
10872 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210873
10874 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410875 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
10876 base::size(read_buffer)),
10877 MockRead("HTTP/1.0 200 OK\r\n"),
10878 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10879 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3510880
Ryan Sleevib8d7ea02018-05-07 20:01:0110881 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710882 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3510883
[email protected]8ddf8322012-02-23 18:08:0610884 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710885 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3510886
[email protected]49639fa2011-12-20 23:22:4110887 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3510888
tfarina42834112016-09-22 13:38:2010889 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110890 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3510891
10892 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110893 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510894
[email protected]029c83b62013-01-24 05:28:2010895 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610896 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010897 TestLoadTimingNotReusedWithPac(load_timing_info,
10898 CONNECT_TIMING_HAS_SSL_TIMES);
10899
bnc691fda62016-08-12 00:43:1610900 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210901 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4710902 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3510903
10904 std::string response_text;
bnc691fda62016-08-12 00:43:1610905 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110906 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510907 EXPECT_EQ("Payload", response_text);
10908}
10909
bncd16676a2016-07-20 16:23:0110910TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2010911 HttpRequestInfo request;
10912 request.method = "GET";
bncce36dca22015-04-21 22:11:2310913 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010914 request.traffic_annotation =
10915 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2010916
Ramin Halavatica8d5252018-03-12 05:33:4910917 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10918 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110919 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710920 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2010921
danakj1fd259a02016-04-16 03:17:0910922 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610923 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2010924
10925 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10926 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10927
10928 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410929 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10930 MockWrite("GET / HTTP/1.1\r\n"
10931 "Host: www.example.org\r\n"
10932 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2010933
10934 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410935 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10936 MockRead("HTTP/1.0 200 OK\r\n"),
10937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10938 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2010939
Ryan Sleevib8d7ea02018-05-07 20:01:0110940 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710941 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2010942
10943 TestCompletionCallback callback;
10944
tfarina42834112016-09-22 13:38:2010945 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110946 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2010947
10948 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110949 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010950
bnc691fda62016-08-12 00:43:1610951 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210952 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2010953
10954 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610955 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010956 TestLoadTimingNotReused(load_timing_info,
10957 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10958
10959 std::string response_text;
bnc691fda62016-08-12 00:43:1610960 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110961 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010962 EXPECT_EQ("Payload", response_text);
10963}
10964
bncd16676a2016-07-20 16:23:0110965TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710966 HttpRequestInfo request;
10967 request.method = "GET";
bncce36dca22015-04-21 22:11:2310968 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010969 request.traffic_annotation =
10970 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710971
Lily Houghton8c2f97d2018-01-22 05:06:5910972 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910973 ProxyResolutionService::CreateFixedFromPacResult(
10974 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110975 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710976 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3510977
danakj1fd259a02016-04-16 03:17:0910978 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610979 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3510980
[email protected]e0c27be2009-07-15 13:09:3510981 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
10982 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3710983 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2310984 0x05, // Version
10985 0x01, // Command (CONNECT)
10986 0x00, // Reserved.
10987 0x03, // Address type (DOMAINNAME).
10988 0x0F, // Length of domain (15)
10989 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
10990 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3710991 };
[email protected]e0c27be2009-07-15 13:09:3510992 const char kSOCKS5OkResponse[] =
10993 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
10994
10995 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410996 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
10997 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
10998 MockWrite("GET / HTTP/1.1\r\n"
10999 "Host: www.example.org\r\n"
11000 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511001
11002 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411003 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11004 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11005 MockRead("HTTP/1.0 200 OK\r\n"),
11006 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11007 MockRead("Payload"),
11008 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511009
Ryan Sleevib8d7ea02018-05-07 20:01:0111010 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711011 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511012
[email protected]49639fa2011-12-20 23:22:4111013 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511014
tfarina42834112016-09-22 13:38:2011015 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111016 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511017
11018 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111019 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511020
bnc691fda62016-08-12 00:43:1611021 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211022 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711023 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511024
[email protected]029c83b62013-01-24 05:28:2011025 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611026 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011027 TestLoadTimingNotReusedWithPac(load_timing_info,
11028 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11029
[email protected]e0c27be2009-07-15 13:09:3511030 std::string response_text;
bnc691fda62016-08-12 00:43:1611031 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111032 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511033 EXPECT_EQ("Payload", response_text);
11034}
11035
bncd16676a2016-07-20 16:23:0111036TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711037 HttpRequestInfo request;
11038 request.method = "GET";
bncce36dca22015-04-21 22:11:2311039 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011040 request.traffic_annotation =
11041 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711042
Lily Houghton8c2f97d2018-01-22 05:06:5911043 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911044 ProxyResolutionService::CreateFixedFromPacResult(
11045 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111046 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711047 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511048
danakj1fd259a02016-04-16 03:17:0911049 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611050 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511051
[email protected]e0c27be2009-07-15 13:09:3511052 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11053 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711054 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311055 0x05, // Version
11056 0x01, // Command (CONNECT)
11057 0x00, // Reserved.
11058 0x03, // Address type (DOMAINNAME).
11059 0x0F, // Length of domain (15)
11060 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11061 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711062 };
11063
[email protected]e0c27be2009-07-15 13:09:3511064 const char kSOCKS5OkResponse[] =
11065 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11066
11067 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411068 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311069 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411070 base::size(kSOCKS5OkRequest)),
11071 MockWrite("GET / HTTP/1.1\r\n"
11072 "Host: www.example.org\r\n"
11073 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511074
11075 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411076 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11077 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11078 MockRead("HTTP/1.0 200 OK\r\n"),
11079 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11080 MockRead("Payload"),
11081 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211082
Ryan Sleevib8d7ea02018-05-07 20:01:0111083 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711084 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211085
[email protected]8ddf8322012-02-23 18:08:0611086 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711087 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211088
[email protected]49639fa2011-12-20 23:22:4111089 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211090
tfarina42834112016-09-22 13:38:2011091 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111092 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211093
11094 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111095 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211096
bnc691fda62016-08-12 00:43:1611097 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211098 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711099 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211100
[email protected]029c83b62013-01-24 05:28:2011101 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611102 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011103 TestLoadTimingNotReusedWithPac(load_timing_info,
11104 CONNECT_TIMING_HAS_SSL_TIMES);
11105
[email protected]3cd17242009-06-23 02:59:0211106 std::string response_text;
bnc691fda62016-08-12 00:43:1611107 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111108 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211109 EXPECT_EQ("Payload", response_text);
11110}
11111
[email protected]448d4ca52012-03-04 04:12:2311112namespace {
11113
Matt Menkef6edce752019-03-19 17:21:5611114// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611115
Matt Menkef6edce752019-03-19 17:21:5611116struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611117 std::string proxy_server;
11118 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611119 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811120 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611121};
11122
Matt Menkef6edce752019-03-19 17:21:5611123std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711124 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911125 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611126
bnc525e175a2016-06-20 12:36:4011127 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311128 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111129 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211130 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111131 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211132 url::SchemeHostPort("https", "host.with.alternate", 443),
zhongyi3d4a55e72016-04-22 20:36:4611133 alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611134
11135 return session;
11136}
11137
Matt Menkef6edce752019-03-19 17:21:5611138int GroupIdTransactionHelper(const std::string& url,
11139 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611140 HttpRequestInfo request;
11141 request.method = "GET";
11142 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1011143 request.traffic_annotation =
11144 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611145
bnc691fda62016-08-12 00:43:1611146 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2711147
[email protected]49639fa2011-12-20 23:22:4111148 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0611149
11150 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2011151 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0611152}
11153
[email protected]448d4ca52012-03-04 04:12:2311154} // namespace
11155
Matt Menkef6edce752019-03-19 17:21:5611156TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
11157 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311158 {
Matt Menkef6edce752019-03-19 17:21:5611159 "", // unused
11160 "http://www.example.org/direct",
11161 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11162 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911163 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611164 false,
bncce36dca22015-04-21 22:11:2311165 },
11166 {
Matt Menkef6edce752019-03-19 17:21:5611167 "", // unused
11168 "http://[2001:1418:13:1::25]/direct",
11169 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
11170 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911171 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611172 false,
bncce36dca22015-04-21 22:11:2311173 },
[email protected]04e5be32009-06-26 20:00:3111174
bncce36dca22015-04-21 22:11:2311175 // SSL Tests
11176 {
Matt Menkef6edce752019-03-19 17:21:5611177 "", // unused
11178 "https://www.example.org/direct_ssl",
11179 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11180 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911181 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611182 true,
bncce36dca22015-04-21 22:11:2311183 },
11184 {
Matt Menkef6edce752019-03-19 17:21:5611185 "", // unused
11186 "https://[2001:1418:13:1::25]/direct",
11187 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
11188 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911189 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611190 true,
bncce36dca22015-04-21 22:11:2311191 },
11192 {
Matt Menkef6edce752019-03-19 17:21:5611193 "", // unused
11194 "https://host.with.alternate/direct",
11195 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11196 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911197 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611198 true,
bncce36dca22015-04-21 22:11:2311199 },
[email protected]2d731a32010-04-29 01:04:0611200 };
[email protected]2ff8b312010-04-26 22:20:5411201
Avi Drissman4365a4782018-12-28 19:26:2411202 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911203 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911204 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11205 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911206 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611207 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611208
mmenkee65e7af2015-10-13 17:16:4211209 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5611210 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611211 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911212 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011213 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
11214 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4811215 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611216
11217 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611218 GroupIdTransactionHelper(tests[i].url, session.get()));
11219 EXPECT_EQ(tests[i].expected_group_id,
11220 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2311221 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0611222 }
[email protected]2d731a32010-04-29 01:04:0611223}
11224
Matt Menkef6edce752019-03-19 17:21:5611225TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
11226 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311227 {
Matt Menke4802de62019-03-08 22:47:5011228 "http_proxy",
11229 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611230 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11231 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911232 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011233 false,
bncce36dca22015-04-21 22:11:2311234 },
[email protected]2d731a32010-04-29 01:04:0611235
bncce36dca22015-04-21 22:11:2311236 // SSL Tests
11237 {
Matt Menke4802de62019-03-08 22:47:5011238 "http_proxy",
11239 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5611240 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11241 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911242 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011243 true,
bncce36dca22015-04-21 22:11:2311244 },
[email protected]af3490e2010-10-16 21:02:2911245
bncce36dca22015-04-21 22:11:2311246 {
Matt Menke4802de62019-03-08 22:47:5011247 "http_proxy",
11248 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611249 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11250 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911251 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011252 true,
bncce36dca22015-04-21 22:11:2311253 },
[email protected]45499252013-01-23 17:12:5611254
bncce36dca22015-04-21 22:11:2311255 {
Matt Menke4802de62019-03-08 22:47:5011256 "http_proxy",
11257 "ftp://ftp.google.com/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611258 ClientSocketPool::GroupId(HostPortPair("ftp.google.com", 21),
11259 ClientSocketPool::SocketType::kFtp,
Matt Menkebdf777802019-04-22 19:38:5911260 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011261 false,
bncce36dca22015-04-21 22:11:2311262 },
[email protected]2d731a32010-04-29 01:04:0611263 };
11264
Avi Drissman4365a4782018-12-28 19:26:2411265 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911266 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911267 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11268 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911269 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611270 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611271
mmenkee65e7af2015-10-13 17:16:4211272 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0611273
Matt Menkee8648fa2019-01-17 16:47:0711274 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
11275 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5611276 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3611277 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911278 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011279 mock_pool_manager->SetSocketPool(proxy_server,
11280 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4811281 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611282
11283 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611284 GroupIdTransactionHelper(tests[i].url, session.get()));
11285 EXPECT_EQ(tests[i].expected_group_id,
11286 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0611287 }
[email protected]2d731a32010-04-29 01:04:0611288}
11289
Matt Menkef6edce752019-03-19 17:21:5611290TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
11291 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311292 {
Matt Menke4802de62019-03-08 22:47:5011293 "socks4://socks_proxy:1080",
11294 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5611295 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11296 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911297 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011298 false,
bncce36dca22015-04-21 22:11:2311299 },
11300 {
Matt Menke4802de62019-03-08 22:47:5011301 "socks5://socks_proxy:1080",
11302 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5611303 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11304 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911305 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011306 false,
bncce36dca22015-04-21 22:11:2311307 },
[email protected]2d731a32010-04-29 01:04:0611308
bncce36dca22015-04-21 22:11:2311309 // SSL Tests
11310 {
Matt Menke4802de62019-03-08 22:47:5011311 "socks4://socks_proxy:1080",
11312 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5611313 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11314 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911315 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011316 true,
bncce36dca22015-04-21 22:11:2311317 },
11318 {
Matt Menke4802de62019-03-08 22:47:5011319 "socks5://socks_proxy:1080",
11320 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5611321 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11322 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911323 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011324 true,
bncce36dca22015-04-21 22:11:2311325 },
[email protected]af3490e2010-10-16 21:02:2911326
bncce36dca22015-04-21 22:11:2311327 {
Matt Menke4802de62019-03-08 22:47:5011328 "socks4://socks_proxy:1080",
11329 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611330 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11331 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911332 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011333 true,
bncce36dca22015-04-21 22:11:2311334 },
[email protected]04e5be32009-06-26 20:00:3111335 };
11336
Avi Drissman4365a4782018-12-28 19:26:2411337 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911338 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911339 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11340 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911341 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611342 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0211343
mmenkee65e7af2015-10-13 17:16:4211344 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3111345
Matt Menkee8648fa2019-01-17 16:47:0711346 ProxyServer proxy_server(
11347 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
11348 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5611349 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611350 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911351 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011352 mock_pool_manager->SetSocketPool(proxy_server,
11353 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4811354 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3111355
bnc691fda62016-08-12 00:43:1611356 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3111357
[email protected]2d731a32010-04-29 01:04:0611358 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611359 GroupIdTransactionHelper(tests[i].url, session.get()));
11360 EXPECT_EQ(tests[i].expected_group_id,
11361 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3111362 }
11363}
11364
bncd16676a2016-07-20 16:23:0111365TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2711366 HttpRequestInfo request;
11367 request.method = "GET";
bncce36dca22015-04-21 22:11:2311368 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011369 request.traffic_annotation =
11370 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711371
Ramin Halavatica8d5252018-03-12 05:33:4911372 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11373 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3211374
[email protected]69719062010-01-05 20:09:2111375 // This simulates failure resolving all hostnames; that means we will fail
11376 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0711377 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3211378
danakj1fd259a02016-04-16 03:17:0911379 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611380 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2511381
[email protected]49639fa2011-12-20 23:22:4111382 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2511383
tfarina42834112016-09-22 13:38:2011384 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111385 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2511386
[email protected]9172a982009-06-06 00:30:2511387 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111388 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2511389}
11390
[email protected]0877e3d2009-10-17 22:29:5711391// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0111392TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5711393 HttpRequestInfo request;
11394 request.method = "GET";
11395 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011396 request.traffic_annotation =
11397 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711398
11399 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0611400 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711401 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111402 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0711403 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911404 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711405
[email protected]49639fa2011-12-20 23:22:4111406 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711407
bnc691fda62016-08-12 00:43:1611408 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711409
tfarina42834112016-09-22 13:38:2011410 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111411 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711412
11413 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111414 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5911415
11416 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611417 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911418 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711419}
11420
zmo9528c9f42015-08-04 22:12:0811421// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0111422TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5711423 HttpRequestInfo request;
11424 request.method = "GET";
11425 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011426 request.traffic_annotation =
11427 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711428
11429 MockRead data_reads[] = {
11430 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0611431 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711432 };
11433
Ryan Sleevib8d7ea02018-05-07 20:01:0111434 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711435 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911436 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711437
[email protected]49639fa2011-12-20 23:22:4111438 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711439
bnc691fda62016-08-12 00:43:1611440 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711441
tfarina42834112016-09-22 13:38:2011442 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111443 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711444
11445 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111446 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811447
bnc691fda62016-08-12 00:43:1611448 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211449 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0811450
wezca1070932016-05-26 20:30:5211451 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0811452 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11453
11454 std::string response_data;
bnc691fda62016-08-12 00:43:1611455 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111456 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811457 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5911458
11459 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611460 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911461 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711462}
11463
11464// Make sure that a dropped connection while draining the body for auth
11465// restart does the right thing.
bncd16676a2016-07-20 16:23:0111466TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5711467 HttpRequestInfo request;
11468 request.method = "GET";
bncce36dca22015-04-21 22:11:2311469 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011470 request.traffic_annotation =
11471 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711472
11473 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311474 MockWrite(
11475 "GET / HTTP/1.1\r\n"
11476 "Host: www.example.org\r\n"
11477 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711478 };
11479
11480 MockRead data_reads1[] = {
11481 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
11482 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11483 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11484 MockRead("Content-Length: 14\r\n\r\n"),
11485 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0611486 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711487 };
11488
Ryan Sleevib8d7ea02018-05-07 20:01:0111489 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0711490 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5711491
bnc691fda62016-08-12 00:43:1611492 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5711493 // be issuing -- the final header line contains the credentials.
11494 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311495 MockWrite(
11496 "GET / HTTP/1.1\r\n"
11497 "Host: www.example.org\r\n"
11498 "Connection: keep-alive\r\n"
11499 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711500 };
11501
11502 // Lastly, the server responds with the actual content.
11503 MockRead data_reads2[] = {
11504 MockRead("HTTP/1.1 200 OK\r\n"),
11505 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11506 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611507 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711508 };
11509
Ryan Sleevib8d7ea02018-05-07 20:01:0111510 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0711511 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0911512 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711513
[email protected]49639fa2011-12-20 23:22:4111514 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5711515
bnc691fda62016-08-12 00:43:1611516 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011517
tfarina42834112016-09-22 13:38:2011518 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111519 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711520
11521 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111522 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711523
bnc691fda62016-08-12 00:43:1611524 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211525 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811526 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5711527
[email protected]49639fa2011-12-20 23:22:4111528 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5711529
bnc691fda62016-08-12 00:43:1611530 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0111531 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711532
11533 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111534 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711535
bnc691fda62016-08-12 00:43:1611536 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211537 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811538 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5711539 EXPECT_EQ(100, response->headers->GetContentLength());
11540}
11541
11542// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0111543TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4911544 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11545 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711546
11547 HttpRequestInfo request;
11548 request.method = "GET";
bncce36dca22015-04-21 22:11:2311549 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011550 request.traffic_annotation =
11551 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711552
11553 MockRead proxy_reads[] = {
11554 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0611555 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5711556 };
11557
Ryan Sleevib8d7ea02018-05-07 20:01:0111558 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0611559 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5711560
[email protected]bb88e1d32013-05-03 23:11:0711561 session_deps_.socket_factory->AddSocketDataProvider(&data);
11562 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5711563
[email protected]49639fa2011-12-20 23:22:4111564 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711565
[email protected]bb88e1d32013-05-03 23:11:0711566 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5711567
danakj1fd259a02016-04-16 03:17:0911568 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611569 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711570
tfarina42834112016-09-22 13:38:2011571 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111572 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711573
11574 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111575 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5711576}
11577
bncd16676a2016-07-20 16:23:0111578TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4611579 HttpRequestInfo request;
11580 request.method = "GET";
bncce36dca22015-04-21 22:11:2311581 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011582 request.traffic_annotation =
11583 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4611584
danakj1fd259a02016-04-16 03:17:0911585 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611586 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711587
[email protected]e22e1362009-11-23 21:31:1211588 MockRead data_reads[] = {
11589 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611590 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1211591 };
[email protected]9492e4a2010-02-24 00:58:4611592
Ryan Sleevib8d7ea02018-05-07 20:01:0111593 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711594 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4611595
[email protected]49639fa2011-12-20 23:22:4111596 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4611597
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]9492e4a2010-02-24 00:58:4611600
robpercival214763f2016-07-01 23:27:0111601 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4611602
bnc691fda62016-08-12 00:43:1611603 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211604 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4611605
wezca1070932016-05-26 20:30:5211606 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4611607 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11608
11609 std::string response_data;
bnc691fda62016-08-12 00:43:1611610 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111611 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1211612}
11613
bncd16676a2016-07-20 16:23:0111614TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1511615 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5211616 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1411617 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2111618 UploadFileElementReader::ScopedOverridingContentLengthForTests
11619 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3311620
danakj1fd259a02016-04-16 03:17:0911621 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911622 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411623 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0711624 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211625 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711626
11627 HttpRequestInfo request;
11628 request.method = "POST";
bncce36dca22015-04-21 22:11:2311629 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711630 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011631 request.traffic_annotation =
11632 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711633
danakj1fd259a02016-04-16 03:17:0911634 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611635 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3311636
11637 MockRead data_reads[] = {
11638 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11639 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0611640 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3311641 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111642 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711643 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3311644
[email protected]49639fa2011-12-20 23:22:4111645 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3311646
tfarina42834112016-09-22 13:38:2011647 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111648 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3311649
11650 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111651 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3311652
bnc691fda62016-08-12 00:43:1611653 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211654 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3311655
maksim.sisove869bf52016-06-23 17:11:5211656 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3311657
[email protected]dd3aa792013-07-16 19:10:2311658 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3311659}
11660
bncd16676a2016-07-20 16:23:0111661TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1511662 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5211663 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3611664 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4811665 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
11666 base::WriteFile(temp_file, temp_file_content.c_str(),
11667 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1111668 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3611669
danakj1fd259a02016-04-16 03:17:0911670 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911671 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411672 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0711673 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211674 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711675
11676 HttpRequestInfo request;
11677 request.method = "POST";
bncce36dca22015-04-21 22:11:2311678 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711679 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011680 request.traffic_annotation =
11681 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711682
[email protected]999dd8c2013-11-12 06:45:5411683 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0911684 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611685 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3611686
Ryan Sleevib8d7ea02018-05-07 20:01:0111687 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0711688 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3611689
[email protected]49639fa2011-12-20 23:22:4111690 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3611691
tfarina42834112016-09-22 13:38:2011692 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3611694
11695 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111696 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3611697
[email protected]dd3aa792013-07-16 19:10:2311698 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3611699}
11700
bncd16676a2016-07-20 16:23:0111701TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0311702 class FakeUploadElementReader : public UploadElementReader {
11703 public:
Chris Watkins7a41d3552017-12-01 02:13:2711704 FakeUploadElementReader() = default;
11705 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0311706
Matt Menkecc1d3a902018-02-05 18:27:3311707 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0311708
11709 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3311710 int Init(CompletionOnceCallback callback) override {
11711 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0311712 return ERR_IO_PENDING;
11713 }
avibf0746c2015-12-09 19:53:1411714 uint64_t GetContentLength() const override { return 0; }
11715 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2011716 int Read(IOBuffer* buf,
11717 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3311718 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0311719 return ERR_FAILED;
11720 }
11721
11722 private:
Matt Menkecc1d3a902018-02-05 18:27:3311723 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0311724 };
11725
11726 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0911727 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11728 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2211729 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0311730
11731 HttpRequestInfo request;
11732 request.method = "POST";
bncce36dca22015-04-21 22:11:2311733 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0311734 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011735 request.traffic_annotation =
11736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0311737
danakj1fd259a02016-04-16 03:17:0911738 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5811739 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911740 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0311741
11742 StaticSocketDataProvider data;
11743 session_deps_.socket_factory->AddSocketDataProvider(&data);
11744
11745 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2011746 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111747 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5511748 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0311749
11750 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3311751 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
11752 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0311753
11754 // Return Init()'s result after the transaction gets destroyed.
11755 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3311756 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0311757}
11758
[email protected]aeefc9e82010-02-19 16:18:2711759// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0111760TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2711761 HttpRequestInfo request;
11762 request.method = "GET";
bncce36dca22015-04-21 22:11:2311763 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011764 request.traffic_annotation =
11765 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2711766
11767 // First transaction will request a resource and receive a Basic challenge
11768 // with realm="first_realm".
11769 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311770 MockWrite(
11771 "GET / HTTP/1.1\r\n"
11772 "Host: www.example.org\r\n"
11773 "Connection: keep-alive\r\n"
11774 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711775 };
11776 MockRead data_reads1[] = {
11777 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11778 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11779 "\r\n"),
11780 };
11781
bnc691fda62016-08-12 00:43:1611782 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2711783 // for first_realm. The server will reject and provide a challenge with
11784 // second_realm.
11785 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311786 MockWrite(
11787 "GET / HTTP/1.1\r\n"
11788 "Host: www.example.org\r\n"
11789 "Connection: keep-alive\r\n"
11790 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
11791 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711792 };
11793 MockRead data_reads2[] = {
11794 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11795 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
11796 "\r\n"),
11797 };
11798
11799 // This again fails, and goes back to first_realm. Make sure that the
11800 // entry is removed from cache.
11801 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2311802 MockWrite(
11803 "GET / HTTP/1.1\r\n"
11804 "Host: www.example.org\r\n"
11805 "Connection: keep-alive\r\n"
11806 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
11807 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711808 };
11809 MockRead data_reads3[] = {
11810 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11811 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11812 "\r\n"),
11813 };
11814
11815 // Try one last time (with the correct password) and get the resource.
11816 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2311817 MockWrite(
11818 "GET / HTTP/1.1\r\n"
11819 "Host: www.example.org\r\n"
11820 "Connection: keep-alive\r\n"
11821 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
11822 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711823 };
11824 MockRead data_reads4[] = {
11825 MockRead("HTTP/1.1 200 OK\r\n"
11826 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5011827 "Content-Length: 5\r\n"
11828 "\r\n"
11829 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2711830 };
11831
Ryan Sleevib8d7ea02018-05-07 20:01:0111832 StaticSocketDataProvider data1(data_reads1, data_writes1);
11833 StaticSocketDataProvider data2(data_reads2, data_writes2);
11834 StaticSocketDataProvider data3(data_reads3, data_writes3);
11835 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0711836 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11837 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11838 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11839 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2711840
[email protected]49639fa2011-12-20 23:22:4111841 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2711842
danakj1fd259a02016-04-16 03:17:0911843 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611844 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011845
[email protected]aeefc9e82010-02-19 16:18:2711846 // Issue the first request with Authorize headers. There should be a
11847 // password prompt for first_realm waiting to be filled in after the
11848 // transaction completes.
tfarina42834112016-09-22 13:38:2011849 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111850 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711851 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111852 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611853 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211854 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811855 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211856 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411857 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311858 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411859 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911860 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711861
11862 // Issue the second request with an incorrect password. There should be a
11863 // password prompt for second_realm waiting to be filled in after the
11864 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4111865 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1611866 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
11867 callback2.callback());
robpercival214763f2016-07-01 23:27:0111868 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711869 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111870 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611871 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211872 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811873 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211874 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411875 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311876 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411877 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911878 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711879
11880 // Issue the third request with another incorrect password. There should be
11881 // a password prompt for first_realm waiting to be filled in. If the password
11882 // prompt is not present, it indicates that the HttpAuthCacheEntry for
11883 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4111884 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1611885 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
11886 callback3.callback());
robpercival214763f2016-07-01 23:27:0111887 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711888 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0111889 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611890 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211891 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811892 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211893 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411894 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311895 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411896 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911897 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711898
11899 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4111900 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1611901 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
11902 callback4.callback());
robpercival214763f2016-07-01 23:27:0111903 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711904 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0111905 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611906 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211907 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811908 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2711909}
11910
Bence Béky230ac612017-08-30 19:17:0811911// Regression test for https://crbug.com/754395.
11912TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
11913 MockRead data_reads[] = {
11914 MockRead("HTTP/1.1 200 OK\r\n"),
11915 MockRead(kAlternativeServiceHttpHeader),
11916 MockRead("\r\n"),
11917 MockRead("hello world"),
11918 MockRead(SYNCHRONOUS, OK),
11919 };
11920
11921 HttpRequestInfo request;
11922 request.method = "GET";
11923 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011924 request.traffic_annotation =
11925 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0811926
Ryan Sleevib8d7ea02018-05-07 20:01:0111927 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0811928 session_deps_.socket_factory->AddSocketDataProvider(&data);
11929
11930 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4911931 ssl.ssl_info.cert =
11932 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
11933 ASSERT_TRUE(ssl.ssl_info.cert);
11934 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0811935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11936
11937 TestCompletionCallback callback;
11938
11939 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11940 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11941
11942 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11943 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11944
11945 url::SchemeHostPort test_server(request.url);
11946 HttpServerProperties* http_server_properties =
11947 session->http_server_properties();
11948 EXPECT_TRUE(
11949 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
11950
11951 EXPECT_THAT(callback.WaitForResult(), IsOk());
11952
11953 const HttpResponseInfo* response = trans.GetResponseInfo();
11954 ASSERT_TRUE(response);
11955 ASSERT_TRUE(response->headers);
11956 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11957 EXPECT_FALSE(response->was_fetched_via_spdy);
11958 EXPECT_FALSE(response->was_alpn_negotiated);
11959
11960 std::string response_data;
11961 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
11962 EXPECT_EQ("hello world", response_data);
11963
11964 EXPECT_TRUE(
11965 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
11966}
11967
bncd16676a2016-07-20 16:23:0111968TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5211969 MockRead data_reads[] = {
11970 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4311971 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5211972 MockRead("\r\n"),
11973 MockRead("hello world"),
11974 MockRead(SYNCHRONOUS, OK),
11975 };
11976
11977 HttpRequestInfo request;
11978 request.method = "GET";
bncb26024382016-06-29 02:39:4511979 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011980 request.traffic_annotation =
11981 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5211982
Ryan Sleevib8d7ea02018-05-07 20:01:0111983 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5211984 session_deps_.socket_factory->AddSocketDataProvider(&data);
11985
bncb26024382016-06-29 02:39:4511986 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4911987 ssl.ssl_info.cert =
11988 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
11989 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4511990 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11991
bncc958faa2015-07-31 18:14:5211992 TestCompletionCallback callback;
11993
danakj1fd259a02016-04-16 03:17:0911994 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611995 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5211996
tfarina42834112016-09-22 13:38:2011997 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111998 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5211999
bncb26024382016-06-29 02:39:4512000 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012001 HttpServerProperties* http_server_properties =
12002 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412003 EXPECT_TRUE(
12004 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bncc958faa2015-07-31 18:14:5212005
robpercival214763f2016-07-01 23:27:0112006 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212007
bnc691fda62016-08-12 00:43:1612008 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212009 ASSERT_TRUE(response);
12010 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212011 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12012 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212013 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212014
12015 std::string response_data;
bnc691fda62016-08-12 00:43:1612016 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212017 EXPECT_EQ("hello world", response_data);
12018
zhongyic4de03032017-05-19 04:07:3412019 AlternativeServiceInfoVector alternative_service_info_vector =
12020 http_server_properties->GetAlternativeServiceInfos(test_server);
12021 ASSERT_EQ(1u, alternative_service_info_vector.size());
12022 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12023 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412024 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212025}
12026
bnce3dd56f2016-06-01 10:37:1112027// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0112028TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112029 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1112030 MockRead data_reads[] = {
12031 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312032 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1112033 MockRead("\r\n"),
12034 MockRead("hello world"),
12035 MockRead(SYNCHRONOUS, OK),
12036 };
12037
12038 HttpRequestInfo request;
12039 request.method = "GET";
12040 request.url = GURL("http://www.example.org/");
12041 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012042 request.traffic_annotation =
12043 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112044
Ryan Sleevib8d7ea02018-05-07 20:01:0112045 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112046 session_deps_.socket_factory->AddSocketDataProvider(&data);
12047
12048 TestCompletionCallback callback;
12049
12050 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612051 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112052
12053 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012054 HttpServerProperties* http_server_properties =
12055 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412056 EXPECT_TRUE(
12057 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnce3dd56f2016-06-01 10:37:1112058
tfarina42834112016-09-22 13:38:2012059 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112060 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12061 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1112062
bnc691fda62016-08-12 00:43:1612063 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1112064 ASSERT_TRUE(response);
12065 ASSERT_TRUE(response->headers);
12066 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12067 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212068 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1112069
12070 std::string response_data;
bnc691fda62016-08-12 00:43:1612071 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1112072 EXPECT_EQ("hello world", response_data);
12073
zhongyic4de03032017-05-19 04:07:3412074 EXPECT_TRUE(
12075 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnce3dd56f2016-06-01 10:37:1112076}
12077
bnca86731e2017-04-17 12:31:2812078// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2512079// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0112080TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2512081 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2812082 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4512083
bnc8bef8da22016-05-30 01:28:2512084 HttpRequestInfo request;
12085 request.method = "GET";
bncb26024382016-06-29 02:39:4512086 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2512087 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012088 request.traffic_annotation =
12089 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2512090
12091 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12092 StaticSocketDataProvider first_data;
12093 first_data.set_connect_data(mock_connect);
12094 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512095 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612096 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512097 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2512098
12099 MockRead data_reads[] = {
12100 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12101 MockRead(ASYNC, OK),
12102 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112103 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2512104 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12105
12106 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12107
bnc525e175a2016-06-20 12:36:4012108 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2512109 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112110 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
12111 444);
bnc8bef8da22016-05-30 01:28:2512112 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112113 http_server_properties->SetHttp2AlternativeService(
bnc8bef8da22016-05-30 01:28:2512114 url::SchemeHostPort(request.url), alternative_service, expiration);
12115
bnc691fda62016-08-12 00:43:1612116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2512117 TestCompletionCallback callback;
12118
tfarina42834112016-09-22 13:38:2012119 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2512120 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112121 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2512122}
12123
bnce3dd56f2016-06-01 10:37:1112124// Regression test for https://crbug.com/615497:
12125// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0112126TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112127 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1112128 HttpRequestInfo request;
12129 request.method = "GET";
12130 request.url = GURL("http://www.example.org/");
12131 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012132 request.traffic_annotation =
12133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112134
12135 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12136 StaticSocketDataProvider first_data;
12137 first_data.set_connect_data(mock_connect);
12138 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
12139
12140 MockRead data_reads[] = {
12141 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12142 MockRead(ASYNC, OK),
12143 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112144 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112145 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12146
12147 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12148
bnc525e175a2016-06-20 12:36:4012149 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1112150 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112151 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1112152 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112153 http_server_properties->SetHttp2AlternativeService(
bnce3dd56f2016-06-01 10:37:1112154 url::SchemeHostPort(request.url), alternative_service, expiration);
12155
bnc691fda62016-08-12 00:43:1612156 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112157 TestCompletionCallback callback;
12158
tfarina42834112016-09-22 13:38:2012159 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1112160 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112161 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1112162}
12163
bncd16676a2016-07-20 16:23:0112164TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0812165 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0912166 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012167 HttpServerProperties* http_server_properties =
12168 session->http_server_properties();
bncb26024382016-06-29 02:39:4512169 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2112170 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0812171 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112172 http_server_properties->SetQuicAlternativeService(
12173 test_server, alternative_service, expiration,
12174 session->params().quic_supported_versions);
zhongyic4de03032017-05-19 04:07:3412175 EXPECT_EQ(
12176 1u,
12177 http_server_properties->GetAlternativeServiceInfos(test_server).size());
bnc4f575852015-10-14 18:35:0812178
12179 // Send a clear header.
12180 MockRead data_reads[] = {
12181 MockRead("HTTP/1.1 200 OK\r\n"),
12182 MockRead("Alt-Svc: clear\r\n"),
12183 MockRead("\r\n"),
12184 MockRead("hello world"),
12185 MockRead(SYNCHRONOUS, OK),
12186 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112187 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0812188 session_deps_.socket_factory->AddSocketDataProvider(&data);
12189
bncb26024382016-06-29 02:39:4512190 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912191 ssl.ssl_info.cert =
12192 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12193 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12195
bnc4f575852015-10-14 18:35:0812196 HttpRequestInfo request;
12197 request.method = "GET";
bncb26024382016-06-29 02:39:4512198 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012199 request.traffic_annotation =
12200 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0812201
12202 TestCompletionCallback callback;
12203
bnc691fda62016-08-12 00:43:1612204 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0812205
tfarina42834112016-09-22 13:38:2012206 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112207 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0812208
bnc691fda62016-08-12 00:43:1612209 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212210 ASSERT_TRUE(response);
12211 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0812212 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12213 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212214 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0812215
12216 std::string response_data;
bnc691fda62016-08-12 00:43:1612217 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0812218 EXPECT_EQ("hello world", response_data);
12219
zhongyic4de03032017-05-19 04:07:3412220 EXPECT_TRUE(
12221 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnc4f575852015-10-14 18:35:0812222}
12223
bncd16676a2016-07-20 16:23:0112224TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5212225 MockRead data_reads[] = {
12226 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312227 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
12228 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5212229 MockRead("hello world"),
12230 MockRead(SYNCHRONOUS, OK),
12231 };
12232
12233 HttpRequestInfo request;
12234 request.method = "GET";
bncb26024382016-06-29 02:39:4512235 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012236 request.traffic_annotation =
12237 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212238
Ryan Sleevib8d7ea02018-05-07 20:01:0112239 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212240 session_deps_.socket_factory->AddSocketDataProvider(&data);
12241
bncb26024382016-06-29 02:39:4512242 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912243 ssl.ssl_info.cert =
12244 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12245 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512246 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12247
bncc958faa2015-07-31 18:14:5212248 TestCompletionCallback callback;
12249
danakj1fd259a02016-04-16 03:17:0912250 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612251 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212252
tfarina42834112016-09-22 13:38:2012253 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112254 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212255
bncb26024382016-06-29 02:39:4512256 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4012257 HttpServerProperties* http_server_properties =
12258 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412259 EXPECT_TRUE(
12260 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bncc958faa2015-07-31 18:14:5212261
robpercival214763f2016-07-01 23:27:0112262 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212263
bnc691fda62016-08-12 00:43:1612264 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212265 ASSERT_TRUE(response);
12266 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212267 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12268 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212269 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212270
12271 std::string response_data;
bnc691fda62016-08-12 00:43:1612272 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212273 EXPECT_EQ("hello world", response_data);
12274
zhongyic4de03032017-05-19 04:07:3412275 AlternativeServiceInfoVector alternative_service_info_vector =
12276 http_server_properties->GetAlternativeServiceInfos(test_server);
12277 ASSERT_EQ(2u, alternative_service_info_vector.size());
12278
12279 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
12280 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412281 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412282 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
12283 1234);
12284 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5412285 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5212286}
12287
bncd16676a2016-07-20 16:23:0112288TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612289 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212290 HostPortPair alternative("alternative.example.org", 443);
12291 std::string origin_url = "https://origin.example.org:443";
12292 std::string alternative_url = "https://alternative.example.org:443";
12293
12294 // Negotiate HTTP/1.1 with alternative.example.org.
12295 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612296 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212297 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12298
12299 // HTTP/1.1 data for request.
12300 MockWrite http_writes[] = {
12301 MockWrite("GET / HTTP/1.1\r\n"
12302 "Host: alternative.example.org\r\n"
12303 "Connection: keep-alive\r\n\r\n"),
12304 };
12305
12306 MockRead http_reads[] = {
12307 MockRead("HTTP/1.1 200 OK\r\n"
12308 "Content-Type: text/html; charset=iso-8859-1\r\n"
12309 "Content-Length: 40\r\n\r\n"
12310 "first HTTP/1.1 response from alternative"),
12311 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112312 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212313 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12314
12315 StaticSocketDataProvider data_refused;
12316 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12317 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12318
zhongyi3d4a55e72016-04-22 20:36:4612319 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0912320 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012321 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212322 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112323 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0212324 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112325 http_server_properties->SetQuicAlternativeService(
12326 server, alternative_service, expiration,
12327 HttpNetworkSession::Params().quic_supported_versions);
zhongyi48704c182015-12-07 07:52:0212328 // Mark the QUIC alternative service as broken.
12329 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
12330
zhongyi48704c182015-12-07 07:52:0212331 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612332 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212333 request.method = "GET";
12334 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012335 request.traffic_annotation =
12336 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12337
zhongyi48704c182015-12-07 07:52:0212338 TestCompletionCallback callback;
12339 NetErrorDetails details;
12340 EXPECT_FALSE(details.quic_broken);
12341
tfarina42834112016-09-22 13:38:2012342 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612343 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212344 EXPECT_TRUE(details.quic_broken);
12345}
12346
bncd16676a2016-07-20 16:23:0112347TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612348 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212349 HostPortPair alternative1("alternative1.example.org", 443);
12350 HostPortPair alternative2("alternative2.example.org", 443);
12351 std::string origin_url = "https://origin.example.org:443";
12352 std::string alternative_url1 = "https://alternative1.example.org:443";
12353 std::string alternative_url2 = "https://alternative2.example.org:443";
12354
12355 // Negotiate HTTP/1.1 with alternative1.example.org.
12356 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612357 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12359
12360 // HTTP/1.1 data for request.
12361 MockWrite http_writes[] = {
12362 MockWrite("GET / HTTP/1.1\r\n"
12363 "Host: alternative1.example.org\r\n"
12364 "Connection: keep-alive\r\n\r\n"),
12365 };
12366
12367 MockRead http_reads[] = {
12368 MockRead("HTTP/1.1 200 OK\r\n"
12369 "Content-Type: text/html; charset=iso-8859-1\r\n"
12370 "Content-Length: 40\r\n\r\n"
12371 "first HTTP/1.1 response from alternative1"),
12372 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112373 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212374 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12375
12376 StaticSocketDataProvider data_refused;
12377 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12378 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12379
danakj1fd259a02016-04-16 03:17:0912380 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012381 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212382 session->http_server_properties();
12383
zhongyi3d4a55e72016-04-22 20:36:4612384 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0212385 AlternativeServiceInfoVector alternative_service_info_vector;
12386 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12387
bnc3472afd2016-11-17 15:27:2112388 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2112389 alternative_service_info_vector.push_back(
12390 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12391 alternative_service1, expiration,
12392 session->params().quic_supported_versions));
bnc3472afd2016-11-17 15:27:2112393 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2112394 alternative_service_info_vector.push_back(
12395 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12396 alternative_service2, expiration,
12397 session->params().quic_supported_versions));
zhongyi48704c182015-12-07 07:52:0212398
12399 http_server_properties->SetAlternativeServices(
zhongyi3d4a55e72016-04-22 20:36:4612400 server, alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0212401
12402 // Mark one of the QUIC alternative service as broken.
12403 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
zhongyic4de03032017-05-19 04:07:3412404 EXPECT_EQ(2u,
12405 http_server_properties->GetAlternativeServiceInfos(server).size());
zhongyi48704c182015-12-07 07:52:0212406
zhongyi48704c182015-12-07 07:52:0212407 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612408 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212409 request.method = "GET";
12410 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012411 request.traffic_annotation =
12412 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12413
zhongyi48704c182015-12-07 07:52:0212414 TestCompletionCallback callback;
12415 NetErrorDetails details;
12416 EXPECT_FALSE(details.quic_broken);
12417
tfarina42834112016-09-22 13:38:2012418 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612419 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212420 EXPECT_FALSE(details.quic_broken);
12421}
12422
bncd16676a2016-07-20 16:23:0112423TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4212424 HttpRequestInfo request;
12425 request.method = "GET";
bncb26024382016-06-29 02:39:4512426 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012427 request.traffic_annotation =
12428 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4212429
[email protected]d973e99a2012-02-17 21:02:3612430 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4212431 StaticSocketDataProvider first_data;
12432 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712433 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512434 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612435 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512436 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4212437
12438 MockRead data_reads[] = {
12439 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12440 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612441 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4212442 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112443 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712444 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4212445
danakj1fd259a02016-04-16 03:17:0912446 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4212447
bnc525e175a2016-06-20 12:36:4012448 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312449 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4612450 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1112451 // Port must be < 1024, or the header will be ignored (since initial port was
12452 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2112453 // Port is ignored by MockConnect anyway.
12454 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12455 666);
bnc7dc7e1b42015-07-28 14:43:1212456 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112457 http_server_properties->SetHttp2AlternativeService(
12458 server, alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4212459
bnc691fda62016-08-12 00:43:1612460 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112461 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4212462
tfarina42834112016-09-22 13:38:2012463 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112464 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12465 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4212466
bnc691fda62016-08-12 00:43:1612467 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212468 ASSERT_TRUE(response);
12469 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4212470 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12471
12472 std::string response_data;
bnc691fda62016-08-12 00:43:1612473 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4212474 EXPECT_EQ("hello world", response_data);
12475
zhongyic4de03032017-05-19 04:07:3412476 const AlternativeServiceInfoVector alternative_service_info_vector =
12477 http_server_properties->GetAlternativeServiceInfos(server);
12478 ASSERT_EQ(1u, alternative_service_info_vector.size());
12479 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412480 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412481 EXPECT_TRUE(
12482 http_server_properties->IsAlternativeServiceBroken(alternative_service));
[email protected]564b4912010-03-09 16:30:4212483}
12484
bnc55ff9da2015-08-19 18:42:3512485// Ensure that we are not allowed to redirect traffic via an alternate protocol
12486// to an unrestricted (port >= 1024) when the original traffic was on a
12487// restricted port (port < 1024). Ensure that we can redirect in all other
12488// cases.
bncd16676a2016-07-20 16:23:0112489TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1112490 HttpRequestInfo restricted_port_request;
12491 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512492 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112493 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012494 restricted_port_request.traffic_annotation =
12495 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112496
[email protected]d973e99a2012-02-17 21:02:3612497 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112498 StaticSocketDataProvider first_data;
12499 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712500 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112501
12502 MockRead data_reads[] = {
12503 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12504 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612505 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112506 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112507 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712508 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512509 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612510 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512511 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112512
danakj1fd259a02016-04-16 03:17:0912513 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112514
bnc525e175a2016-06-20 12:36:4012515 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312516 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112517 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112518 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12519 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212520 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112521 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612522 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012523 expiration);
[email protected]3912662a32011-10-04 00:51:1112524
bnc691fda62016-08-12 00:43:1612525 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112526 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112527
tfarina42834112016-09-22 13:38:2012528 int rv = trans.Start(&restricted_port_request, callback.callback(),
12529 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112530 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112531 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0112532 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1912533}
[email protected]3912662a32011-10-04 00:51:1112534
bnc55ff9da2015-08-19 18:42:3512535// Ensure that we are allowed to redirect traffic via an alternate protocol to
12536// an unrestricted (port >= 1024) when the original traffic was on a restricted
12537// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0112538TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0712539 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1912540
12541 HttpRequestInfo restricted_port_request;
12542 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512543 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1912544 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012545 restricted_port_request.traffic_annotation =
12546 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1912547
12548 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12549 StaticSocketDataProvider first_data;
12550 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712551 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1912552
12553 MockRead data_reads[] = {
12554 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12555 MockRead("hello world"),
12556 MockRead(ASYNC, OK),
12557 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112558 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712559 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512560 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612561 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512562 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1912563
danakj1fd259a02016-04-16 03:17:0912564 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1912565
bnc525e175a2016-06-20 12:36:4012566 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1912567 session->http_server_properties();
12568 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112569 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12570 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212571 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112572 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612573 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012574 expiration);
[email protected]c54c6962013-02-01 04:53:1912575
bnc691fda62016-08-12 00:43:1612576 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1912577 TestCompletionCallback callback;
12578
tfarina42834112016-09-22 13:38:2012579 EXPECT_EQ(ERR_IO_PENDING,
12580 trans.Start(&restricted_port_request, callback.callback(),
12581 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1912582 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0112583 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112584}
12585
bnc55ff9da2015-08-19 18:42:3512586// Ensure that we are not allowed to redirect traffic via an alternate protocol
12587// to an unrestricted (port >= 1024) when the original traffic was on a
12588// restricted port (port < 1024). Ensure that we can redirect in all other
12589// cases.
bncd16676a2016-07-20 16:23:0112590TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1112591 HttpRequestInfo restricted_port_request;
12592 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512593 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112594 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012595 restricted_port_request.traffic_annotation =
12596 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112597
[email protected]d973e99a2012-02-17 21:02:3612598 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112599 StaticSocketDataProvider first_data;
12600 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712601 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112602
12603 MockRead data_reads[] = {
12604 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12605 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612606 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112607 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112608 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712609 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112610
bncb26024382016-06-29 02:39:4512611 SSLSocketDataProvider ssl(ASYNC, OK);
12612 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12613
danakj1fd259a02016-04-16 03:17:0912614 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112615
bnc525e175a2016-06-20 12:36:4012616 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312617 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112618 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112619 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12620 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212621 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112622 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612623 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012624 expiration);
[email protected]3912662a32011-10-04 00:51:1112625
bnc691fda62016-08-12 00:43:1612626 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112627 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112628
tfarina42834112016-09-22 13:38:2012629 int rv = trans.Start(&restricted_port_request, callback.callback(),
12630 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112631 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112632 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112633 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112634}
12635
bnc55ff9da2015-08-19 18:42:3512636// Ensure that we are not allowed to redirect traffic via an alternate protocol
12637// to an unrestricted (port >= 1024) when the original traffic was on a
12638// restricted port (port < 1024). Ensure that we can redirect in all other
12639// cases.
bncd16676a2016-07-20 16:23:0112640TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1112641 HttpRequestInfo unrestricted_port_request;
12642 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512643 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112644 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012645 unrestricted_port_request.traffic_annotation =
12646 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112647
[email protected]d973e99a2012-02-17 21:02:3612648 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112649 StaticSocketDataProvider first_data;
12650 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712651 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112652
12653 MockRead data_reads[] = {
12654 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12655 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612656 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112657 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112658 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712659 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512660 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612661 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512662 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112663
danakj1fd259a02016-04-16 03:17:0912664 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112665
bnc525e175a2016-06-20 12:36:4012666 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312667 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112668 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112669 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12670 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212671 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112672 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612673 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012674 expiration);
[email protected]3912662a32011-10-04 00:51:1112675
bnc691fda62016-08-12 00:43:1612676 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112677 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112678
bnc691fda62016-08-12 00:43:1612679 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012680 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112681 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112682 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112683 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112684}
12685
bnc55ff9da2015-08-19 18:42:3512686// Ensure that we are not allowed to redirect traffic via an alternate protocol
12687// to an unrestricted (port >= 1024) when the original traffic was on a
12688// restricted port (port < 1024). Ensure that we can redirect in all other
12689// cases.
bncd16676a2016-07-20 16:23:0112690TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1112691 HttpRequestInfo unrestricted_port_request;
12692 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512693 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112694 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012695 unrestricted_port_request.traffic_annotation =
12696 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112697
[email protected]d973e99a2012-02-17 21:02:3612698 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112699 StaticSocketDataProvider first_data;
12700 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712701 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112702
12703 MockRead data_reads[] = {
12704 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12705 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612706 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112707 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112708 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712709 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112710
bncb26024382016-06-29 02:39:4512711 SSLSocketDataProvider ssl(ASYNC, OK);
12712 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12713
danakj1fd259a02016-04-16 03:17:0912714 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112715
bnc525e175a2016-06-20 12:36:4012716 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312717 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2212718 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2112719 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12720 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212721 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112722 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612723 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012724 expiration);
[email protected]3912662a32011-10-04 00:51:1112725
bnc691fda62016-08-12 00:43:1612726 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112727 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112728
bnc691fda62016-08-12 00:43:1612729 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012730 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112731 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112732 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0112733 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112734}
12735
bnc55ff9da2015-08-19 18:42:3512736// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2112737// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
12738// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0112739TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0212740 HttpRequestInfo request;
12741 request.method = "GET";
bncce36dca22015-04-21 22:11:2312742 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012743 request.traffic_annotation =
12744 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0212745
12746 // The alternate protocol request will error out before we attempt to connect,
12747 // so only the standard HTTP request will try to connect.
12748 MockRead data_reads[] = {
12749 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12750 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612751 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0212752 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112753 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712754 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0212755
danakj1fd259a02016-04-16 03:17:0912756 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0212757
bnc525e175a2016-06-20 12:36:4012758 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0212759 session->http_server_properties();
12760 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2112761 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12762 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1212763 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112764 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612765 url::SchemeHostPort(request.url), alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0212766
bnc691fda62016-08-12 00:43:1612767 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0212768 TestCompletionCallback callback;
12769
tfarina42834112016-09-22 13:38:2012770 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112771 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0212772 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0112773 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212774
bnc691fda62016-08-12 00:43:1612775 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212776 ASSERT_TRUE(response);
12777 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0212778 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12779
12780 std::string response_data;
bnc691fda62016-08-12 00:43:1612781 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212782 EXPECT_EQ("hello world", response_data);
12783}
12784
bncd16676a2016-07-20 16:23:0112785TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5412786 HttpRequestInfo request;
12787 request.method = "GET";
bncb26024382016-06-29 02:39:4512788 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012789 request.traffic_annotation =
12790 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5412791
12792 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212793 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312794 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212795 MockRead("\r\n"),
12796 MockRead("hello world"),
12797 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12798 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5412799
Ryan Sleevib8d7ea02018-05-07 20:01:0112800 StaticSocketDataProvider first_transaction(data_reads,
12801 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712802 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4512803 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612804 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512805 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5412806
bnc032658ba2016-09-26 18:17:1512807 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5412808
Ryan Hamilton0239aac2018-05-19 00:03:1312809 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4512810 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4112811 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5412812
Raul Tambre94493c652019-03-11 17:18:3512813 spdy::SpdySerializedFrame resp(
12814 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1312815 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5412816 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112817 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5412818 };
12819
Ryan Sleevib8d7ea02018-05-07 20:01:0112820 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0712821 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5412822
[email protected]d973e99a2012-02-17 21:02:3612823 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0112824 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5512825 hanging_non_alternate_protocol_socket.set_connect_data(
12826 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0712827 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5512828 &hanging_non_alternate_protocol_socket);
12829
[email protected]49639fa2011-12-20 23:22:4112830 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5412831
danakj1fd259a02016-04-16 03:17:0912832 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812833 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912834 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412835
tfarina42834112016-09-22 13:38:2012836 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112837 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12838 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412839
12840 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212841 ASSERT_TRUE(response);
12842 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5412843 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12844
12845 std::string response_data;
robpercival214763f2016-07-01 23:27:0112846 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412847 EXPECT_EQ("hello world", response_data);
12848
bnc87dcefc2017-05-25 12:47:5812849 trans =
Jeremy Roman0579ed62017-08-29 15:56:1912850 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412851
tfarina42834112016-09-22 13:38:2012852 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112853 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12854 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412855
12856 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212857 ASSERT_TRUE(response);
12858 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212859 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5312860 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212861 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5412862
robpercival214763f2016-07-01 23:27:0112863 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412864 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5412865}
12866
bncd16676a2016-07-20 16:23:0112867TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5512868 HttpRequestInfo request;
12869 request.method = "GET";
bncb26024382016-06-29 02:39:4512870 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012871 request.traffic_annotation =
12872 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5512873
bncb26024382016-06-29 02:39:4512874 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5512875 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212876 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312877 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212878 MockRead("\r\n"),
12879 MockRead("hello world"),
12880 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12881 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5512882 };
12883
Ryan Sleevib8d7ea02018-05-07 20:01:0112884 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4512885 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5512886
bncb26024382016-06-29 02:39:4512887 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912888 ssl_http11.ssl_info.cert =
12889 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12890 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4512891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
12892
12893 // Second transaction starts an alternative and a non-alternative Job.
12894 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3612895 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0112896 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1812897 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1812898 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
12899
Ryan Sleevib8d7ea02018-05-07 20:01:0112900 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1812901 hanging_socket2.set_connect_data(never_finishing_connect);
12902 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5512903
bncb26024382016-06-29 02:39:4512904 // Third transaction starts an alternative and a non-alternative job.
12905 // The non-alternative job hangs, but the alternative one succeeds.
12906 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1312907 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4512908 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1312909 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4512910 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5512911 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4112912 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5512913 };
Raul Tambre94493c652019-03-11 17:18:3512914 spdy::SpdySerializedFrame resp1(
12915 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1312916 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3512917 spdy::SpdySerializedFrame resp2(
12918 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1312919 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5512920 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112921 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
12922 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1312923 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5512924 };
12925
Ryan Sleevib8d7ea02018-05-07 20:01:0112926 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0712927 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5512928
bnc032658ba2016-09-26 18:17:1512929 AddSSLSocketData();
bncb26024382016-06-29 02:39:4512930
Ryan Sleevib8d7ea02018-05-07 20:01:0112931 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1812932 hanging_socket3.set_connect_data(never_finishing_connect);
12933 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5512934
danakj1fd259a02016-04-16 03:17:0912935 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4112936 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5012937 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5512938
tfarina42834112016-09-22 13:38:2012939 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112940 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12941 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5512942
12943 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5212944 ASSERT_TRUE(response);
12945 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5512946 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12947
12948 std::string response_data;
robpercival214763f2016-07-01 23:27:0112949 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512950 EXPECT_EQ("hello world", response_data);
12951
[email protected]49639fa2011-12-20 23:22:4112952 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5012953 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2012954 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112955 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5512956
[email protected]49639fa2011-12-20 23:22:4112957 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5012958 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2012959 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112960 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5512961
robpercival214763f2016-07-01 23:27:0112962 EXPECT_THAT(callback2.WaitForResult(), IsOk());
12963 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5512964
12965 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5212966 ASSERT_TRUE(response);
12967 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212968 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5512969 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212970 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0112971 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512972 EXPECT_EQ("hello!", response_data);
12973
12974 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5212975 ASSERT_TRUE(response);
12976 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212977 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5512978 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212979 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0112980 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512981 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5512982}
12983
bncd16676a2016-07-20 16:23:0112984TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5312985 session_deps_.host_resolver->set_synchronous_mode(true);
12986
[email protected]2d6728692011-03-12 01:39:5512987 HttpRequestInfo request;
12988 request.method = "GET";
bncb26024382016-06-29 02:39:4512989 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012990 request.traffic_annotation =
12991 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5512992
12993 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212994 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312995 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212996 MockRead("\r\n"),
12997 MockRead("hello world"),
12998 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12999 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513000 };
13001
Ryan Sleevib8d7ea02018-05-07 20:01:0113002 StaticSocketDataProvider first_transaction(data_reads,
13003 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713004 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513005
[email protected]8ddf8322012-02-23 18:08:0613006 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913007 ssl.ssl_info.cert =
13008 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13009 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713010 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513011
[email protected]d973e99a2012-02-17 21:02:3613012 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113013 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513014 hanging_alternate_protocol_socket.set_connect_data(
13015 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713016 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513017 &hanging_alternate_protocol_socket);
13018
bncb26024382016-06-29 02:39:4513019 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0113020 StaticSocketDataProvider second_transaction(data_reads,
13021 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1813022 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4513023 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513024
[email protected]49639fa2011-12-20 23:22:4113025 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5513026
danakj1fd259a02016-04-16 03:17:0913027 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813028 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913029 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513030
tfarina42834112016-09-22 13:38:2013031 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113032 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13033 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513034
13035 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213036 ASSERT_TRUE(response);
13037 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513038 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13039
13040 std::string response_data;
robpercival214763f2016-07-01 23:27:0113041 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513042 EXPECT_EQ("hello world", response_data);
13043
bnc87dcefc2017-05-25 12:47:5813044 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913045 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513046
tfarina42834112016-09-22 13:38:2013047 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113048 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13049 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513050
13051 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213052 ASSERT_TRUE(response);
13053 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513054 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13055 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213056 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5513057
robpercival214763f2016-07-01 23:27:0113058 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513059 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5513060}
13061
bnc2e884782016-08-11 19:45:1913062// Test that proxy is resolved using the origin url,
13063// regardless of the alternative server.
13064TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
13065 // Configure proxy to bypass www.example.org, which is the origin URL.
13066 ProxyConfig proxy_config;
13067 proxy_config.proxy_rules().ParseFromString("myproxy:70");
13068 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4913069 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
13070 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1913071
13072 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1913073 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1913074 &capturing_proxy_resolver);
13075
13076 TestNetLog net_log;
13077
Bence Béky53a5aef2018-03-29 21:54:1213078 session_deps_.proxy_resolution_service =
13079 std::make_unique<ProxyResolutionService>(
13080 std::move(proxy_config_service), std::move(proxy_resolver_factory),
13081 &net_log);
bnc2e884782016-08-11 19:45:1913082
13083 session_deps_.net_log = &net_log;
13084
13085 // Configure alternative service with a hostname that is not bypassed by the
13086 // proxy.
13087 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13088 HttpServerProperties* http_server_properties =
13089 session->http_server_properties();
13090 url::SchemeHostPort server("https", "www.example.org", 443);
13091 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2113092 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1913093 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113094 http_server_properties->SetHttp2AlternativeService(
13095 server, alternative_service, expiration);
bnc2e884782016-08-11 19:45:1913096
13097 // Non-alternative job should hang.
13098 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113099 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1913100 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
13101 session_deps_.socket_factory->AddSocketDataProvider(
13102 &hanging_alternate_protocol_socket);
13103
bnc032658ba2016-09-26 18:17:1513104 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1913105
13106 HttpRequestInfo request;
13107 request.method = "GET";
13108 request.url = GURL("https://www.example.org/");
13109 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013110 request.traffic_annotation =
13111 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1913112
Ryan Hamilton0239aac2018-05-19 00:03:1313113 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1913114 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
13115
13116 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
13117
Ryan Hamilton0239aac2018-05-19 00:03:1313118 spdy::SpdySerializedFrame resp(
13119 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
13120 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1913121 MockRead spdy_reads[] = {
13122 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
13123 };
13124
Ryan Sleevib8d7ea02018-05-07 20:01:0113125 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1913126 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
13127
13128 TestCompletionCallback callback;
13129
13130 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13131
tfarina42834112016-09-22 13:38:2013132 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1913133 EXPECT_THAT(callback.GetResult(rv), IsOk());
13134
13135 const HttpResponseInfo* response = trans.GetResponseInfo();
13136 ASSERT_TRUE(response);
13137 ASSERT_TRUE(response->headers);
13138 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
13139 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213140 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1913141
13142 std::string response_data;
13143 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13144 EXPECT_EQ("hello!", response_data);
13145
13146 // Origin host bypasses proxy, no resolution should have happened.
13147 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
13148}
13149
bncd16676a2016-07-20 16:23:0113150TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1113151 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4213152 proxy_config.set_auto_detect(true);
13153 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1113154
sammc5dd160c2015-04-02 02:43:1313155 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4913156 session_deps_.proxy_resolution_service =
13157 std::make_unique<ProxyResolutionService>(
13158 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
13159 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
13160 std::make_unique<CapturingProxyResolverFactory>(
13161 &capturing_proxy_resolver),
13162 nullptr);
vishal.b62985ca92015-04-17 08:45:5113163 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0713164 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1113165
13166 HttpRequestInfo request;
13167 request.method = "GET";
bncb26024382016-06-29 02:39:4513168 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013169 request.traffic_annotation =
13170 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1113171
13172 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213173 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313174 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213175 MockRead("\r\n"),
13176 MockRead("hello world"),
13177 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13178 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1113179 };
13180
Ryan Sleevib8d7ea02018-05-07 20:01:0113181 StaticSocketDataProvider first_transaction(data_reads,
13182 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713183 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513184 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613185 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1113187
bnc032658ba2016-09-26 18:17:1513188 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1113189
Ryan Hamilton0239aac2018-05-19 00:03:1313190 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513191 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1113192 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313193 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2513194 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13195 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1313196 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4113197 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1113198 };
13199
[email protected]d911f1b2010-05-05 22:39:4213200 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
13201
Raul Tambre94493c652019-03-11 17:18:3513202 spdy::SpdySerializedFrame resp(
13203 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313204 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1113205 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113206 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
13207 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1113208 };
13209
Ryan Sleevib8d7ea02018-05-07 20:01:0113210 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713211 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1113212
[email protected]d973e99a2012-02-17 21:02:3613213 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113214 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513215 hanging_non_alternate_protocol_socket.set_connect_data(
13216 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713217 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513218 &hanging_non_alternate_protocol_socket);
13219
[email protected]49639fa2011-12-20 23:22:4113220 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1113221
danakj1fd259a02016-04-16 03:17:0913222 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813223 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913224 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113225
tfarina42834112016-09-22 13:38:2013226 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4113227 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13228 EXPECT_THAT(callback.WaitForResult(), IsOk());
13229
13230 const HttpResponseInfo* response = trans->GetResponseInfo();
13231 ASSERT_TRUE(response);
13232 ASSERT_TRUE(response->headers);
13233 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
13234 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213235 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4113236
13237 std::string response_data;
13238 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
13239 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1113240
bnc87dcefc2017-05-25 12:47:5813241 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913242 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113243
tfarina42834112016-09-22 13:38:2013244 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113245 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13246 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1113247
mmenkea2dcd3bf2016-08-16 21:49:4113248 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213249 ASSERT_TRUE(response);
13250 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213251 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313252 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213253 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1113254
robpercival214763f2016-07-01 23:27:0113255 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1113256 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4513257 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
13258 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313259 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2313260 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313261 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1113262
[email protected]029c83b62013-01-24 05:28:2013263 LoadTimingInfo load_timing_info;
13264 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
13265 TestLoadTimingNotReusedWithPac(load_timing_info,
13266 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1113267}
[email protected]631f1322010-04-30 17:59:1113268
bncd16676a2016-07-20 16:23:0113269TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4813270 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5413271 HttpRequestInfo request;
13272 request.method = "GET";
bncb26024382016-06-29 02:39:4513273 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013274 request.traffic_annotation =
13275 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413276
13277 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213278 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313279 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213280 MockRead("\r\n"),
13281 MockRead("hello world"),
13282 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5413283 };
13284
Ryan Sleevib8d7ea02018-05-07 20:01:0113285 StaticSocketDataProvider first_transaction(data_reads,
13286 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713287 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513288 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613289 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513290 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413291
bnc032658ba2016-09-26 18:17:1513292 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413293
Ryan Hamilton0239aac2018-05-19 00:03:1313294 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513295 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113296 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413297
Raul Tambre94493c652019-03-11 17:18:3513298 spdy::SpdySerializedFrame resp(
13299 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313300 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413301 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113302 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413303 };
13304
Ryan Sleevib8d7ea02018-05-07 20:01:0113305 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713306 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413307
[email protected]83039bb2011-12-09 18:43:5513308 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413309
danakj1fd259a02016-04-16 03:17:0913310 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5413311
bnc87dcefc2017-05-25 12:47:5813312 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913313 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413314
tfarina42834112016-09-22 13:38:2013315 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113316 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13317 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413318
13319 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213320 ASSERT_TRUE(response);
13321 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413322 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13323
13324 std::string response_data;
robpercival214763f2016-07-01 23:27:0113325 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413326 EXPECT_EQ("hello world", response_data);
13327
13328 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2513329 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4013330 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1113331 PRIVACY_MODE_DISABLED,
13332 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2713333 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5213334 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3813335
bnc87dcefc2017-05-25 12:47:5813336 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913337 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413338
tfarina42834112016-09-22 13:38:2013339 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113340 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13341 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413342
13343 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213344 ASSERT_TRUE(response);
13345 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213346 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313347 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213348 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413349
robpercival214763f2016-07-01 23:27:0113350 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413351 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4213352}
13353
[email protected]044de0642010-06-17 10:42:1513354// GenerateAuthToken is a mighty big test.
13355// It tests all permutation of GenerateAuthToken behavior:
13356// - Synchronous and Asynchronous completion.
13357// - OK or error on completion.
13358// - Direct connection, non-authenticating proxy, and authenticating proxy.
13359// - HTTP or HTTPS backend (to include proxy tunneling).
13360// - Non-authenticating and authenticating backend.
13361//
[email protected]fe3b7dc2012-02-03 19:52:0913362// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1513363// problems generating an auth token for an authenticating proxy, we don't
13364// need to test all permutations of the backend server).
13365//
13366// The test proceeds by going over each of the configuration cases, and
13367// potentially running up to three rounds in each of the tests. The TestConfig
13368// specifies both the configuration for the test as well as the expectations
13369// for the results.
bncd16676a2016-07-20 16:23:0113370TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5013371 static const char kServer[] = "http://www.example.com";
13372 static const char kSecureServer[] = "https://www.example.com";
13373 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1513374
13375 enum AuthTiming {
13376 AUTH_NONE,
13377 AUTH_SYNC,
13378 AUTH_ASYNC,
13379 };
13380
13381 const MockWrite kGet(
13382 "GET / HTTP/1.1\r\n"
13383 "Host: www.example.com\r\n"
13384 "Connection: keep-alive\r\n\r\n");
13385 const MockWrite kGetProxy(
13386 "GET http://www.example.com/ HTTP/1.1\r\n"
13387 "Host: www.example.com\r\n"
13388 "Proxy-Connection: keep-alive\r\n\r\n");
13389 const MockWrite kGetAuth(
13390 "GET / HTTP/1.1\r\n"
13391 "Host: www.example.com\r\n"
13392 "Connection: keep-alive\r\n"
13393 "Authorization: auth_token\r\n\r\n");
13394 const MockWrite kGetProxyAuth(
13395 "GET http://www.example.com/ HTTP/1.1\r\n"
13396 "Host: www.example.com\r\n"
13397 "Proxy-Connection: keep-alive\r\n"
13398 "Proxy-Authorization: auth_token\r\n\r\n");
13399 const MockWrite kGetAuthThroughProxy(
13400 "GET http://www.example.com/ HTTP/1.1\r\n"
13401 "Host: www.example.com\r\n"
13402 "Proxy-Connection: keep-alive\r\n"
13403 "Authorization: auth_token\r\n\r\n");
13404 const MockWrite kGetAuthWithProxyAuth(
13405 "GET http://www.example.com/ HTTP/1.1\r\n"
13406 "Host: www.example.com\r\n"
13407 "Proxy-Connection: keep-alive\r\n"
13408 "Proxy-Authorization: auth_token\r\n"
13409 "Authorization: auth_token\r\n\r\n");
13410 const MockWrite kConnect(
13411 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713412 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513413 "Proxy-Connection: keep-alive\r\n\r\n");
13414 const MockWrite kConnectProxyAuth(
13415 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713416 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513417 "Proxy-Connection: keep-alive\r\n"
13418 "Proxy-Authorization: auth_token\r\n\r\n");
13419
13420 const MockRead kSuccess(
13421 "HTTP/1.1 200 OK\r\n"
13422 "Content-Type: text/html; charset=iso-8859-1\r\n"
13423 "Content-Length: 3\r\n\r\n"
13424 "Yes");
13425 const MockRead kFailure(
13426 "Should not be called.");
13427 const MockRead kServerChallenge(
13428 "HTTP/1.1 401 Unauthorized\r\n"
13429 "WWW-Authenticate: Mock realm=server\r\n"
13430 "Content-Type: text/html; charset=iso-8859-1\r\n"
13431 "Content-Length: 14\r\n\r\n"
13432 "Unauthorized\r\n");
13433 const MockRead kProxyChallenge(
13434 "HTTP/1.1 407 Unauthorized\r\n"
13435 "Proxy-Authenticate: Mock realm=proxy\r\n"
13436 "Proxy-Connection: close\r\n"
13437 "Content-Type: text/html; charset=iso-8859-1\r\n"
13438 "Content-Length: 14\r\n\r\n"
13439 "Unauthorized\r\n");
13440 const MockRead kProxyConnected(
13441 "HTTP/1.1 200 Connection Established\r\n\r\n");
13442
13443 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
13444 // no constructors, but the C++ compiler on Windows warns about
13445 // unspecified data in compound literals. So, moved to using constructors,
13446 // and TestRound's created with the default constructor should not be used.
13447 struct TestRound {
13448 TestRound()
Raul Tambre94493c652019-03-11 17:18:3513449 : expected_rv(ERR_UNEXPECTED),
13450 extra_write(nullptr),
13451 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4313452 TestRound(const MockWrite& write_arg,
13453 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1513454 int expected_rv_arg)
13455 : write(write_arg),
13456 read(read_arg),
13457 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3513458 extra_write(nullptr),
13459 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1513460 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
13461 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0113462 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1513463 : write(write_arg),
13464 read(read_arg),
13465 expected_rv(expected_rv_arg),
13466 extra_write(extra_write_arg),
13467 extra_read(extra_read_arg) {
13468 }
13469 MockWrite write;
13470 MockRead read;
13471 int expected_rv;
13472 const MockWrite* extra_write;
13473 const MockRead* extra_read;
13474 };
13475
13476 static const int kNoSSL = 500;
13477
13478 struct TestConfig {
asanka463ca4262016-11-16 02:34:3113479 int line_number;
thestig9d3bb0c2015-01-24 00:49:5113480 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1513481 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3113482 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5113483 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1513484 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3113485 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1513486 int num_auth_rounds;
13487 int first_ssl_round;
asankae2257db2016-10-11 22:03:1613488 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1513489 } test_configs[] = {
asankac93076192016-10-03 15:46:0213490 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113491 {__LINE__,
13492 nullptr,
asankac93076192016-10-03 15:46:0213493 AUTH_NONE,
13494 OK,
13495 kServer,
13496 AUTH_NONE,
13497 OK,
13498 1,
13499 kNoSSL,
13500 {TestRound(kGet, kSuccess, OK)}},
13501 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113502 {__LINE__,
13503 nullptr,
asankac93076192016-10-03 15:46:0213504 AUTH_NONE,
13505 OK,
13506 kServer,
13507 AUTH_SYNC,
13508 OK,
13509 2,
13510 kNoSSL,
13511 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513512 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113513 {__LINE__,
13514 nullptr,
asankac93076192016-10-03 15:46:0213515 AUTH_NONE,
13516 OK,
13517 kServer,
13518 AUTH_SYNC,
13519 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613520 3,
13521 kNoSSL,
13522 {TestRound(kGet, kServerChallenge, OK),
13523 TestRound(kGet, kServerChallenge, OK),
13524 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113525 {__LINE__,
13526 nullptr,
asankae2257db2016-10-11 22:03:1613527 AUTH_NONE,
13528 OK,
13529 kServer,
13530 AUTH_SYNC,
13531 ERR_UNSUPPORTED_AUTH_SCHEME,
13532 2,
13533 kNoSSL,
13534 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113535 {__LINE__,
13536 nullptr,
asankae2257db2016-10-11 22:03:1613537 AUTH_NONE,
13538 OK,
13539 kServer,
13540 AUTH_SYNC,
13541 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
13542 2,
13543 kNoSSL,
13544 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113545 {__LINE__,
13546 kProxy,
asankae2257db2016-10-11 22:03:1613547 AUTH_SYNC,
13548 ERR_FAILED,
13549 kServer,
13550 AUTH_NONE,
13551 OK,
13552 2,
13553 kNoSSL,
13554 {TestRound(kGetProxy, kProxyChallenge, OK),
13555 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113556 {__LINE__,
13557 kProxy,
asankae2257db2016-10-11 22:03:1613558 AUTH_ASYNC,
13559 ERR_FAILED,
13560 kServer,
13561 AUTH_NONE,
13562 OK,
13563 2,
13564 kNoSSL,
13565 {TestRound(kGetProxy, kProxyChallenge, OK),
13566 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113567 {__LINE__,
13568 nullptr,
asankae2257db2016-10-11 22:03:1613569 AUTH_NONE,
13570 OK,
13571 kServer,
13572 AUTH_SYNC,
13573 ERR_FAILED,
asankac93076192016-10-03 15:46:0213574 2,
13575 kNoSSL,
13576 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613577 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113578 {__LINE__,
13579 nullptr,
asankae2257db2016-10-11 22:03:1613580 AUTH_NONE,
13581 OK,
13582 kServer,
13583 AUTH_ASYNC,
13584 ERR_FAILED,
13585 2,
13586 kNoSSL,
13587 {TestRound(kGet, kServerChallenge, OK),
13588 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113589 {__LINE__,
13590 nullptr,
asankac93076192016-10-03 15:46:0213591 AUTH_NONE,
13592 OK,
13593 kServer,
13594 AUTH_ASYNC,
13595 OK,
13596 2,
13597 kNoSSL,
13598 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513599 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113600 {__LINE__,
13601 nullptr,
asankac93076192016-10-03 15:46:0213602 AUTH_NONE,
13603 OK,
13604 kServer,
13605 AUTH_ASYNC,
13606 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613607 3,
asankac93076192016-10-03 15:46:0213608 kNoSSL,
13609 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613610 // The second round uses a HttpAuthHandlerMock that always succeeds.
13611 TestRound(kGet, kServerChallenge, OK),
13612 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213613 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113614 {__LINE__,
13615 kProxy,
asankac93076192016-10-03 15:46:0213616 AUTH_NONE,
13617 OK,
13618 kServer,
13619 AUTH_NONE,
13620 OK,
13621 1,
13622 kNoSSL,
13623 {TestRound(kGetProxy, kSuccess, OK)}},
13624 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113625 {__LINE__,
13626 kProxy,
asankac93076192016-10-03 15:46:0213627 AUTH_NONE,
13628 OK,
13629 kServer,
13630 AUTH_SYNC,
13631 OK,
13632 2,
13633 kNoSSL,
13634 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513635 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113636 {__LINE__,
13637 kProxy,
asankac93076192016-10-03 15:46:0213638 AUTH_NONE,
13639 OK,
13640 kServer,
13641 AUTH_SYNC,
13642 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613643 3,
asankac93076192016-10-03 15:46:0213644 kNoSSL,
13645 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613646 TestRound(kGetProxy, kServerChallenge, OK),
13647 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113648 {__LINE__,
13649 kProxy,
asankac93076192016-10-03 15:46:0213650 AUTH_NONE,
13651 OK,
13652 kServer,
13653 AUTH_ASYNC,
13654 OK,
13655 2,
13656 kNoSSL,
13657 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513658 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113659 {__LINE__,
13660 kProxy,
asankac93076192016-10-03 15:46:0213661 AUTH_NONE,
13662 OK,
13663 kServer,
13664 AUTH_ASYNC,
13665 ERR_INVALID_AUTH_CREDENTIALS,
13666 2,
13667 kNoSSL,
13668 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613669 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213670 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113671 {__LINE__,
13672 kProxy,
asankac93076192016-10-03 15:46:0213673 AUTH_SYNC,
13674 OK,
13675 kServer,
13676 AUTH_NONE,
13677 OK,
13678 2,
13679 kNoSSL,
13680 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513681 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113682 {__LINE__,
13683 kProxy,
asankac93076192016-10-03 15:46:0213684 AUTH_SYNC,
13685 ERR_INVALID_AUTH_CREDENTIALS,
13686 kServer,
13687 AUTH_NONE,
13688 OK,
13689 2,
13690 kNoSSL,
13691 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613692 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113693 {__LINE__,
13694 kProxy,
asankac93076192016-10-03 15:46:0213695 AUTH_ASYNC,
13696 OK,
13697 kServer,
13698 AUTH_NONE,
13699 OK,
13700 2,
13701 kNoSSL,
13702 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513703 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113704 {__LINE__,
13705 kProxy,
asankac93076192016-10-03 15:46:0213706 AUTH_ASYNC,
13707 ERR_INVALID_AUTH_CREDENTIALS,
13708 kServer,
13709 AUTH_NONE,
13710 OK,
13711 2,
13712 kNoSSL,
13713 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613714 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113715 {__LINE__,
13716 kProxy,
13717 AUTH_ASYNC,
13718 ERR_INVALID_AUTH_CREDENTIALS,
13719 kServer,
13720 AUTH_NONE,
13721 OK,
13722 3,
13723 kNoSSL,
13724 {TestRound(kGetProxy, kProxyChallenge, OK),
13725 TestRound(kGetProxy, kProxyChallenge, OK),
13726 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213727 // Authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113728 {__LINE__,
13729 kProxy,
asankac93076192016-10-03 15:46:0213730 AUTH_SYNC,
13731 OK,
13732 kServer,
13733 AUTH_SYNC,
13734 OK,
13735 3,
13736 kNoSSL,
13737 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513738 TestRound(kGetProxyAuth, kServerChallenge, OK),
13739 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113740 {__LINE__,
13741 kProxy,
asankac93076192016-10-03 15:46:0213742 AUTH_SYNC,
13743 OK,
13744 kServer,
13745 AUTH_SYNC,
13746 ERR_INVALID_AUTH_CREDENTIALS,
13747 3,
13748 kNoSSL,
13749 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513750 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613751 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113752 {__LINE__,
13753 kProxy,
asankac93076192016-10-03 15:46:0213754 AUTH_ASYNC,
13755 OK,
13756 kServer,
13757 AUTH_SYNC,
13758 OK,
13759 3,
13760 kNoSSL,
13761 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513762 TestRound(kGetProxyAuth, kServerChallenge, OK),
13763 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113764 {__LINE__,
13765 kProxy,
asankac93076192016-10-03 15:46:0213766 AUTH_ASYNC,
13767 OK,
13768 kServer,
13769 AUTH_SYNC,
13770 ERR_INVALID_AUTH_CREDENTIALS,
13771 3,
13772 kNoSSL,
13773 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513774 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613775 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113776 {__LINE__,
13777 kProxy,
asankac93076192016-10-03 15:46:0213778 AUTH_SYNC,
13779 OK,
13780 kServer,
13781 AUTH_ASYNC,
13782 OK,
13783 3,
13784 kNoSSL,
13785 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513786 TestRound(kGetProxyAuth, kServerChallenge, OK),
13787 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113788 {__LINE__,
13789 kProxy,
13790 AUTH_SYNC,
13791 ERR_INVALID_AUTH_CREDENTIALS,
13792 kServer,
13793 AUTH_ASYNC,
13794 OK,
13795 4,
13796 kNoSSL,
13797 {TestRound(kGetProxy, kProxyChallenge, OK),
13798 TestRound(kGetProxy, kProxyChallenge, OK),
13799 TestRound(kGetProxyAuth, kServerChallenge, OK),
13800 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
13801 {__LINE__,
13802 kProxy,
asankac93076192016-10-03 15:46:0213803 AUTH_SYNC,
13804 OK,
13805 kServer,
13806 AUTH_ASYNC,
13807 ERR_INVALID_AUTH_CREDENTIALS,
13808 3,
13809 kNoSSL,
13810 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513811 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613812 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113813 {__LINE__,
13814 kProxy,
asankac93076192016-10-03 15:46:0213815 AUTH_ASYNC,
13816 OK,
13817 kServer,
13818 AUTH_ASYNC,
13819 OK,
13820 3,
13821 kNoSSL,
13822 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513823 TestRound(kGetProxyAuth, kServerChallenge, OK),
13824 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113825 {__LINE__,
13826 kProxy,
asankac93076192016-10-03 15:46:0213827 AUTH_ASYNC,
13828 OK,
13829 kServer,
13830 AUTH_ASYNC,
13831 ERR_INVALID_AUTH_CREDENTIALS,
13832 3,
13833 kNoSSL,
13834 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513835 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613836 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113837 {__LINE__,
13838 kProxy,
13839 AUTH_ASYNC,
13840 ERR_INVALID_AUTH_CREDENTIALS,
13841 kServer,
13842 AUTH_ASYNC,
13843 ERR_INVALID_AUTH_CREDENTIALS,
13844 4,
13845 kNoSSL,
13846 {TestRound(kGetProxy, kProxyChallenge, OK),
13847 TestRound(kGetProxy, kProxyChallenge, OK),
13848 TestRound(kGetProxyAuth, kServerChallenge, OK),
13849 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213850 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113851 {__LINE__,
13852 nullptr,
asankac93076192016-10-03 15:46:0213853 AUTH_NONE,
13854 OK,
13855 kSecureServer,
13856 AUTH_NONE,
13857 OK,
13858 1,
13859 0,
13860 {TestRound(kGet, kSuccess, OK)}},
13861 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113862 {__LINE__,
13863 nullptr,
asankac93076192016-10-03 15:46:0213864 AUTH_NONE,
13865 OK,
13866 kSecureServer,
13867 AUTH_SYNC,
13868 OK,
13869 2,
13870 0,
13871 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513872 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113873 {__LINE__,
13874 nullptr,
asankac93076192016-10-03 15:46:0213875 AUTH_NONE,
13876 OK,
13877 kSecureServer,
13878 AUTH_SYNC,
13879 ERR_INVALID_AUTH_CREDENTIALS,
13880 2,
13881 0,
asankae2257db2016-10-11 22:03:1613882 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113883 {__LINE__,
13884 nullptr,
asankac93076192016-10-03 15:46:0213885 AUTH_NONE,
13886 OK,
13887 kSecureServer,
13888 AUTH_ASYNC,
13889 OK,
13890 2,
13891 0,
13892 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513893 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113894 {__LINE__,
13895 nullptr,
asankac93076192016-10-03 15:46:0213896 AUTH_NONE,
13897 OK,
13898 kSecureServer,
13899 AUTH_ASYNC,
13900 ERR_INVALID_AUTH_CREDENTIALS,
13901 2,
13902 0,
asankae2257db2016-10-11 22:03:1613903 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213904 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113905 {__LINE__,
13906 kProxy,
asankac93076192016-10-03 15:46:0213907 AUTH_NONE,
13908 OK,
13909 kSecureServer,
13910 AUTH_NONE,
13911 OK,
13912 1,
13913 0,
13914 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
13915 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113916 {__LINE__,
13917 kProxy,
asankac93076192016-10-03 15:46:0213918 AUTH_NONE,
13919 OK,
13920 kSecureServer,
13921 AUTH_SYNC,
13922 OK,
13923 2,
13924 0,
13925 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1513926 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113927 {__LINE__,
13928 kProxy,
asankac93076192016-10-03 15:46:0213929 AUTH_NONE,
13930 OK,
13931 kSecureServer,
13932 AUTH_SYNC,
13933 ERR_INVALID_AUTH_CREDENTIALS,
13934 2,
13935 0,
13936 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1613937 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113938 {__LINE__,
13939 kProxy,
asankac93076192016-10-03 15:46:0213940 AUTH_NONE,
13941 OK,
13942 kSecureServer,
13943 AUTH_ASYNC,
13944 OK,
13945 2,
13946 0,
13947 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1513948 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113949 {__LINE__,
13950 kProxy,
asankac93076192016-10-03 15:46:0213951 AUTH_NONE,
13952 OK,
13953 kSecureServer,
13954 AUTH_ASYNC,
13955 ERR_INVALID_AUTH_CREDENTIALS,
13956 2,
13957 0,
13958 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1613959 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213960 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113961 {__LINE__,
13962 kProxy,
asankac93076192016-10-03 15:46:0213963 AUTH_SYNC,
13964 OK,
13965 kSecureServer,
13966 AUTH_NONE,
13967 OK,
13968 2,
13969 1,
13970 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513971 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3113972 {__LINE__,
13973 kProxy,
asankac93076192016-10-03 15:46:0213974 AUTH_SYNC,
13975 ERR_INVALID_AUTH_CREDENTIALS,
13976 kSecureServer,
13977 AUTH_NONE,
13978 OK,
13979 2,
13980 kNoSSL,
13981 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613982 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3113983 {__LINE__,
13984 kProxy,
asankae2257db2016-10-11 22:03:1613985 AUTH_SYNC,
13986 ERR_UNSUPPORTED_AUTH_SCHEME,
13987 kSecureServer,
13988 AUTH_NONE,
13989 OK,
13990 2,
13991 kNoSSL,
13992 {TestRound(kConnect, kProxyChallenge, OK),
13993 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3113994 {__LINE__,
13995 kProxy,
asankae2257db2016-10-11 22:03:1613996 AUTH_SYNC,
13997 ERR_UNEXPECTED,
13998 kSecureServer,
13999 AUTH_NONE,
14000 OK,
14001 2,
14002 kNoSSL,
14003 {TestRound(kConnect, kProxyChallenge, OK),
14004 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114005 {__LINE__,
14006 kProxy,
asankac93076192016-10-03 15:46:0214007 AUTH_ASYNC,
14008 OK,
14009 kSecureServer,
14010 AUTH_NONE,
14011 OK,
14012 2,
14013 1,
14014 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514015 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114016 {__LINE__,
14017 kProxy,
asankac93076192016-10-03 15:46:0214018 AUTH_ASYNC,
14019 ERR_INVALID_AUTH_CREDENTIALS,
14020 kSecureServer,
14021 AUTH_NONE,
14022 OK,
14023 2,
14024 kNoSSL,
14025 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614026 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0214027 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114028 {__LINE__,
14029 kProxy,
asankac93076192016-10-03 15:46:0214030 AUTH_SYNC,
14031 OK,
14032 kSecureServer,
14033 AUTH_SYNC,
14034 OK,
14035 3,
14036 1,
14037 {TestRound(kConnect, kProxyChallenge, OK),
14038 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14039 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514040 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114041 {__LINE__,
14042 kProxy,
asankac93076192016-10-03 15:46:0214043 AUTH_SYNC,
14044 OK,
14045 kSecureServer,
14046 AUTH_SYNC,
14047 ERR_INVALID_AUTH_CREDENTIALS,
14048 3,
14049 1,
14050 {TestRound(kConnect, kProxyChallenge, OK),
14051 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14052 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614053 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114054 {__LINE__,
14055 kProxy,
asankac93076192016-10-03 15:46:0214056 AUTH_ASYNC,
14057 OK,
14058 kSecureServer,
14059 AUTH_SYNC,
14060 OK,
14061 3,
14062 1,
14063 {TestRound(kConnect, kProxyChallenge, OK),
14064 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14065 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514066 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114067 {__LINE__,
14068 kProxy,
asankac93076192016-10-03 15:46:0214069 AUTH_ASYNC,
14070 OK,
14071 kSecureServer,
14072 AUTH_SYNC,
14073 ERR_INVALID_AUTH_CREDENTIALS,
14074 3,
14075 1,
14076 {TestRound(kConnect, kProxyChallenge, OK),
14077 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14078 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614079 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114080 {__LINE__,
14081 kProxy,
asankac93076192016-10-03 15:46:0214082 AUTH_SYNC,
14083 OK,
14084 kSecureServer,
14085 AUTH_ASYNC,
14086 OK,
14087 3,
14088 1,
14089 {TestRound(kConnect, kProxyChallenge, OK),
14090 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14091 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514092 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114093 {__LINE__,
14094 kProxy,
asankac93076192016-10-03 15:46:0214095 AUTH_SYNC,
14096 OK,
14097 kSecureServer,
14098 AUTH_ASYNC,
14099 ERR_INVALID_AUTH_CREDENTIALS,
14100 3,
14101 1,
14102 {TestRound(kConnect, kProxyChallenge, OK),
14103 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14104 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614105 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114106 {__LINE__,
14107 kProxy,
asankac93076192016-10-03 15:46:0214108 AUTH_ASYNC,
14109 OK,
14110 kSecureServer,
14111 AUTH_ASYNC,
14112 OK,
14113 3,
14114 1,
14115 {TestRound(kConnect, kProxyChallenge, OK),
14116 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14117 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514118 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114119 {__LINE__,
14120 kProxy,
asankac93076192016-10-03 15:46:0214121 AUTH_ASYNC,
14122 OK,
14123 kSecureServer,
14124 AUTH_ASYNC,
14125 ERR_INVALID_AUTH_CREDENTIALS,
14126 3,
14127 1,
14128 {TestRound(kConnect, kProxyChallenge, OK),
14129 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14130 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614131 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114132 {__LINE__,
14133 kProxy,
14134 AUTH_ASYNC,
14135 ERR_INVALID_AUTH_CREDENTIALS,
14136 kSecureServer,
14137 AUTH_ASYNC,
14138 ERR_INVALID_AUTH_CREDENTIALS,
14139 4,
14140 2,
14141 {TestRound(kConnect, kProxyChallenge, OK),
14142 TestRound(kConnect, kProxyChallenge, OK),
14143 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14144 &kServerChallenge),
14145 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1514146 };
14147
asanka463ca4262016-11-16 02:34:3114148 for (const auto& test_config : test_configs) {
14149 SCOPED_TRACE(::testing::Message() << "Test config at "
14150 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0814151 HttpAuthHandlerMock::Factory* auth_factory(
14152 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714153 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4914154 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2614155
14156 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1514157 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3114158 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0814159 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14160 std::string auth_challenge = "Mock realm=proxy";
14161 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2414162 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14163 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0814164 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2014165 empty_ssl_info, origin,
14166 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814167 auth_handler->SetGenerateExpectation(
14168 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114169 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0814170 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
14171 }
[email protected]044de0642010-06-17 10:42:1514172 }
14173 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0014174 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1514175 std::string auth_challenge = "Mock realm=server";
14176 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2414177 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14178 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1514179 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014180 empty_ssl_info, origin,
14181 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514182 auth_handler->SetGenerateExpectation(
14183 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114184 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0814185 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1614186
14187 // The second handler always succeeds. It should only be used where there
14188 // are multiple auth sessions for server auth in the same network
14189 // transaction using the same auth scheme.
14190 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1914191 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1614192 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
14193 empty_ssl_info, origin,
14194 NetLogWithSource());
14195 second_handler->SetGenerateExpectation(true, OK);
14196 auth_factory->AddMockHandler(second_handler.release(),
14197 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1514198 }
14199 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5914200 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914201 ProxyResolutionService::CreateFixed(test_config.proxy_url,
14202 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514203 } else {
Bence Béky53a5aef2018-03-29 21:54:1214204 session_deps_.proxy_resolution_service =
14205 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1514206 }
14207
14208 HttpRequestInfo request;
14209 request.method = "GET";
14210 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1014211 request.traffic_annotation =
14212 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514213
danakj1fd259a02016-04-16 03:17:0914214 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1514215
rchcb68dc62015-05-21 04:45:3614216 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
14217
14218 std::vector<std::vector<MockRead>> mock_reads(1);
14219 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1514220 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214221 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1514222 const TestRound& read_write_round = test_config.rounds[round];
14223
14224 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3614225 mock_reads.back().push_back(read_write_round.read);
14226 mock_writes.back().push_back(read_write_round.write);
14227
14228 // kProxyChallenge uses Proxy-Connection: close which means that the
14229 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5414230 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3614231 mock_reads.push_back(std::vector<MockRead>());
14232 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1514233 }
14234
rchcb68dc62015-05-21 04:45:3614235 if (read_write_round.extra_read) {
14236 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1514237 }
rchcb68dc62015-05-21 04:45:3614238 if (read_write_round.extra_write) {
14239 mock_writes.back().push_back(*read_write_round.extra_write);
14240 }
[email protected]044de0642010-06-17 10:42:1514241
14242 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1514243 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0714244 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1514245 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3614246 }
[email protected]044de0642010-06-17 10:42:1514247
danakj1fd259a02016-04-16 03:17:0914248 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3614249 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1914250 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0114251 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3614252 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3214253 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3614254 }
14255
mmenkecc2298e2015-12-07 18:20:1814256 // Transaction must be created after DataProviders, so it's destroyed before
14257 // they are as well.
14258 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14259
rchcb68dc62015-05-21 04:45:3614260 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214261 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3614262 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1514263 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4114264 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1514265 int rv;
14266 if (round == 0) {
tfarina42834112016-09-22 13:38:2014267 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514268 } else {
[email protected]49639fa2011-12-20 23:22:4114269 rv = trans.RestartWithAuth(
14270 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1514271 }
14272 if (rv == ERR_IO_PENDING)
14273 rv = callback.WaitForResult();
14274
14275 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1614276 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5014277 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5514278 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1514279 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
14280 continue;
14281 }
14282 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5814283 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1514284 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5814285 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1614286 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1514287 }
14288 }
[email protected]e5ae96a2010-04-14 20:12:4514289 }
14290}
14291
bncd16676a2016-07-20 16:23:0114292TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1414293 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1414294 HttpAuthHandlerMock::Factory* auth_factory(
14295 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714296 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1214297 session_deps_.proxy_resolution_service =
14298 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0714299 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1414300
14301 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14302 auth_handler->set_connection_based(true);
14303 std::string auth_challenge = "Mock realm=server";
14304 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2414305 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14306 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4914307 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1414308 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014309 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814310 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1414311
[email protected]c871bce92010-07-15 21:51:1414312 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3514313 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1414314 HttpRequestInfo request;
14315 request.method = "GET";
14316 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1014317 request.traffic_annotation =
14318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2714319
danakj1fd259a02016-04-16 03:17:0914320 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1014321
14322 // Use a TCP Socket Pool with only one connection per group. This is used
14323 // to validate that the TCP socket is not released to the pool between
14324 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4214325 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3614326 CommonConnectJobParams common_connect_job_params(
14327 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2814328 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5914329 50, // Max sockets for pool
14330 1, // Max sockets per group
14331 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3614332 ProxyServer::Direct(), false, // is_for_websockets
Matt Menked6fd2a52019-03-20 06:14:3614333 &common_connect_job_params, session_deps_.ssl_config_service.get());
Jeremy Roman0579ed62017-08-29 15:56:1914334 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4014335 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
14336 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4814337 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1014338
bnc691fda62016-08-12 00:43:1614339 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114340 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1414341
14342 const MockWrite kGet(
14343 "GET / HTTP/1.1\r\n"
14344 "Host: www.example.com\r\n"
14345 "Connection: keep-alive\r\n\r\n");
14346 const MockWrite kGetAuth(
14347 "GET / HTTP/1.1\r\n"
14348 "Host: www.example.com\r\n"
14349 "Connection: keep-alive\r\n"
14350 "Authorization: auth_token\r\n\r\n");
14351
14352 const MockRead kServerChallenge(
14353 "HTTP/1.1 401 Unauthorized\r\n"
14354 "WWW-Authenticate: Mock realm=server\r\n"
14355 "Content-Type: text/html; charset=iso-8859-1\r\n"
14356 "Content-Length: 14\r\n\r\n"
14357 "Unauthorized\r\n");
14358 const MockRead kSuccess(
14359 "HTTP/1.1 200 OK\r\n"
14360 "Content-Type: text/html; charset=iso-8859-1\r\n"
14361 "Content-Length: 3\r\n\r\n"
14362 "Yes");
14363
14364 MockWrite writes[] = {
14365 // First round
14366 kGet,
14367 // Second round
14368 kGetAuth,
14369 // Third round
14370 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3014371 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1014372 kGetAuth,
14373 // Competing request
14374 kGet,
[email protected]c871bce92010-07-15 21:51:1414375 };
14376 MockRead reads[] = {
14377 // First round
14378 kServerChallenge,
14379 // Second round
14380 kServerChallenge,
14381 // Third round
[email protected]eca50e122010-09-11 14:03:3014382 kServerChallenge,
14383 // Fourth round
[email protected]c871bce92010-07-15 21:51:1414384 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1014385 // Competing response
14386 kSuccess,
[email protected]c871bce92010-07-15 21:51:1414387 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114388 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0714389 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1414390
Matt Menkef6edce752019-03-19 17:21:5614391 const ClientSocketPool::GroupId kSocketGroup(
14392 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5914393 PrivacyMode::PRIVACY_MODE_DISABLED);
[email protected]7ef4cbbb2011-02-06 11:19:1014394
14395 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1414396 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2014397 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1414398 if (rv == ERR_IO_PENDING)
14399 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114400 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614401 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214402 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814403 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314404 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114405 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14406 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414407
[email protected]7ef4cbbb2011-02-06 11:19:1014408 // In between rounds, another request comes in for the same domain.
14409 // It should not be able to grab the TCP socket that trans has already
14410 // claimed.
bnc691fda62016-08-12 00:43:1614411 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114412 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2014413 rv = trans_compete.Start(&request, callback_compete.callback(),
14414 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114415 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1014416 // callback_compete.WaitForResult at this point would stall forever,
14417 // since the HttpNetworkTransaction does not release the request back to
14418 // the pool until after authentication completes.
14419
14420 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1414421 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614422 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414423 if (rv == ERR_IO_PENDING)
14424 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114425 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614426 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214427 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814428 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314429 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114430 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14431 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414432
[email protected]7ef4cbbb2011-02-06 11:19:1014433 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1414434 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614435 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414436 if (rv == ERR_IO_PENDING)
14437 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114438 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614439 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214440 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814441 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314442 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114443 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14444 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3014445
[email protected]7ef4cbbb2011-02-06 11:19:1014446 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3014447 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614448 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3014449 if (rv == ERR_IO_PENDING)
14450 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114451 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614452 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214453 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814454 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314455 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014456
asanka463ca4262016-11-16 02:34:3114457 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
14458 // auth handler should transition to a DONE state in concert with the remote
14459 // server. But that's not something we can test here with a mock handler.
14460 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
14461 auth_handler->state());
14462
[email protected]7ef4cbbb2011-02-06 11:19:1014463 // Read the body since the fourth round was successful. This will also
14464 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4414465 scoped_refptr<IOBufferWithSize> io_buf =
14466 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1614467 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014468 if (rv == ERR_IO_PENDING)
14469 rv = callback.WaitForResult();
14470 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614471 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014472 EXPECT_EQ(0, rv);
14473 // There are still 0 idle sockets, since the trans_compete transaction
14474 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314475 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014476
14477 // The competing request can now finish. Wait for the headers and then
14478 // read the body.
14479 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0114480 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614481 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014482 if (rv == ERR_IO_PENDING)
14483 rv = callback.WaitForResult();
14484 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614485 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014486 EXPECT_EQ(0, rv);
14487
14488 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314489 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1414490}
14491
[email protected]65041fa2010-05-21 06:56:5314492// This tests the case that a request is issued via http instead of spdy after
14493// npn is negotiated.
bncd16676a2016-07-20 16:23:0114494TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5314495 HttpRequestInfo request;
14496 request.method = "GET";
bncce36dca22015-04-21 22:11:2314497 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014498 request.traffic_annotation =
14499 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5314500
14501 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314502 MockWrite(
14503 "GET / HTTP/1.1\r\n"
14504 "Host: www.example.org\r\n"
14505 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5314506 };
14507
14508 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214509 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314510 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214511 MockRead("\r\n"),
14512 MockRead("hello world"),
14513 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5314514 };
14515
[email protected]8ddf8322012-02-23 18:08:0614516 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614517 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5314518
[email protected]bb88e1d32013-05-03 23:11:0714519 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5314520
Ryan Sleevib8d7ea02018-05-07 20:01:0114521 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0714522 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5314523
[email protected]49639fa2011-12-20 23:22:4114524 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5314525
danakj1fd259a02016-04-16 03:17:0914526 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614527 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5314528
tfarina42834112016-09-22 13:38:2014529 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5314530
robpercival214763f2016-07-01 23:27:0114531 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14532 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5314533
bnc691fda62016-08-12 00:43:1614534 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214535 ASSERT_TRUE(response);
14536 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5314537 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14538
14539 std::string response_data;
bnc691fda62016-08-12 00:43:1614540 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5314541 EXPECT_EQ("hello world", response_data);
14542
14543 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214544 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5314545}
[email protected]26ef6582010-06-24 02:30:4714546
bnc55ff9da2015-08-19 18:42:3514547// Simulate the SSL handshake completing with an NPN negotiation followed by an
14548// immediate server closing of the socket.
14549// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0114550TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4714551 HttpRequestInfo request;
14552 request.method = "GET";
bncce36dca22015-04-21 22:11:2314553 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014554 request.traffic_annotation =
14555 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4714556
[email protected]8ddf8322012-02-23 18:08:0614557 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614558 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0714559 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4714560
Ryan Hamilton0239aac2018-05-19 00:03:1314561 spdy::SpdySerializedFrame req(
14562 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114563 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4714564
14565 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614566 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4714567 };
14568
Ryan Sleevib8d7ea02018-05-07 20:01:0114569 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714570 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4714571
[email protected]49639fa2011-12-20 23:22:4114572 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4714573
danakj1fd259a02016-04-16 03:17:0914574 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614575 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4714576
tfarina42834112016-09-22 13:38:2014577 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114578 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14579 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4714580}
[email protected]65d34382010-07-01 18:12:2614581
[email protected]795cbf82013-07-22 09:37:2714582// A subclass of HttpAuthHandlerMock that records the request URL when
14583// it gets it. This is needed since the auth handler may get destroyed
14584// before we get a chance to query it.
14585class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
14586 public:
14587 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
14588
Chris Watkins7a41d3552017-12-01 02:13:2714589 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2714590
14591 protected:
dchengb03027d2014-10-21 12:00:2014592 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
14593 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0914594 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2014595 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2714596 *url_ = request->url;
14597 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0914598 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2714599 }
14600
14601 private:
14602 GURL* url_;
14603};
14604
[email protected]8e6441ca2010-08-19 05:56:3814605// Test that if we cancel the transaction as the connection is completing, that
14606// everything tears down correctly.
bncd16676a2016-07-20 16:23:0114607TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3814608 // Setup everything about the connection to complete synchronously, so that
14609 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
14610 // for is the callback from the HttpStreamRequest.
14611 // Then cancel the transaction.
14612 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3614613 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3814614 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614615 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
14616 MockRead(SYNCHRONOUS, "hello world"),
14617 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3814618 };
14619
[email protected]8e6441ca2010-08-19 05:56:3814620 HttpRequestInfo request;
14621 request.method = "GET";
bncce36dca22015-04-21 22:11:2314622 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014623 request.traffic_annotation =
14624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3814625
danakj1fd259a02016-04-16 03:17:0914626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814627 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914628 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2714629
Ryan Sleevib8d7ea02018-05-07 20:01:0114630 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3814631 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714632 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3814633
[email protected]49639fa2011-12-20 23:22:4114634 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3814635
vishal.b62985ca92015-04-17 08:45:5114636 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4114637 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114638 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3814639 trans.reset(); // Cancel the transaction here.
14640
fdoray92e35a72016-06-10 15:54:5514641 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3014642}
14643
[email protected]ecab6e052014-05-16 14:58:1214644// Test that if a transaction is cancelled after receiving the headers, the
14645// stream is drained properly and added back to the socket pool. The main
14646// purpose of this test is to make sure that an HttpStreamParser can be read
14647// from after the HttpNetworkTransaction and the objects it owns have been
14648// deleted.
14649// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0114650TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1214651 MockRead data_reads[] = {
14652 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
14653 MockRead(ASYNC, "Content-Length: 2\r\n"),
14654 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
14655 MockRead(ASYNC, "1"),
14656 // 2 async reads are necessary to trigger a ReadResponseBody call after the
14657 // HttpNetworkTransaction has been deleted.
14658 MockRead(ASYNC, "2"),
14659 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
14660 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114661 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1214662 session_deps_.socket_factory->AddSocketDataProvider(&data);
14663
danakj1fd259a02016-04-16 03:17:0914664 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1214665
14666 {
14667 HttpRequestInfo request;
14668 request.method = "GET";
bncce36dca22015-04-21 22:11:2314669 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014670 request.traffic_annotation =
14671 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1214672
dcheng48459ac22014-08-26 00:46:4114673 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1214674 TestCompletionCallback callback;
14675
tfarina42834112016-09-22 13:38:2014676 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114677 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1214678 callback.WaitForResult();
14679
14680 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214681 ASSERT_TRUE(response);
14682 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1214683 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14684
14685 // The transaction and HttpRequestInfo are deleted.
14686 }
14687
14688 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5514689 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1214690
14691 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4114692 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1214693}
14694
[email protected]76a505b2010-08-25 06:23:0014695// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0114696TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914697 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914698 ProxyResolutionService::CreateFixedFromPacResult(
14699 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114700 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714701 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914702 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014703
[email protected]76a505b2010-08-25 06:23:0014704 HttpRequestInfo request;
14705 request.method = "GET";
bncce36dca22015-04-21 22:11:2314706 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014707 request.traffic_annotation =
14708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014709
14710 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2314711 MockWrite(
14712 "GET http://www.example.org/ HTTP/1.1\r\n"
14713 "Host: www.example.org\r\n"
14714 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014715 };
14716
14717 MockRead data_reads1[] = {
14718 MockRead("HTTP/1.1 200 OK\r\n"),
14719 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14720 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614721 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014722 };
14723
Ryan Sleevib8d7ea02018-05-07 20:01:0114724 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714725 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0014726
[email protected]49639fa2011-12-20 23:22:4114727 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014728
bnc691fda62016-08-12 00:43:1614729 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914730 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614731 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914732 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14733 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014734
bnc691fda62016-08-12 00:43:1614735 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114736 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014737
14738 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114739 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0014740
bnc691fda62016-08-12 00:43:1614741 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214742 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014743
14744 EXPECT_TRUE(response->headers->IsKeepAlive());
14745 EXPECT_EQ(200, response->headers->response_code());
14746 EXPECT_EQ(100, response->headers->GetContentLength());
14747 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714748 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14749 HostPortPair::FromString("myproxy:70")),
14750 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914751 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14752 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14753 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0014754 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2014755
14756 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614757 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014758 TestLoadTimingNotReusedWithPac(load_timing_info,
14759 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0014760}
14761
14762// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0114763TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914764 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914765 ProxyResolutionService::CreateFixedFromPacResult(
14766 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114767 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714768 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914769 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014770
[email protected]76a505b2010-08-25 06:23:0014771 HttpRequestInfo request;
14772 request.method = "GET";
bncce36dca22015-04-21 22:11:2314773 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014774 request.traffic_annotation =
14775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014776
14777 // Since we have proxy, should try to establish tunnel.
14778 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1714779 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14780 "Host: www.example.org:443\r\n"
14781 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014782
rsleevidb16bb02015-11-12 23:47:1714783 MockWrite("GET / HTTP/1.1\r\n"
14784 "Host: www.example.org\r\n"
14785 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014786 };
14787
14788 MockRead data_reads1[] = {
14789 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14790
14791 MockRead("HTTP/1.1 200 OK\r\n"),
14792 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14793 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614794 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014795 };
14796
Ryan Sleevib8d7ea02018-05-07 20:01:0114797 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714798 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0614799 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0714800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0014801
[email protected]49639fa2011-12-20 23:22:4114802 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014803
bnc691fda62016-08-12 00:43:1614804 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914805 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614806 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914807 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14808 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014809
bnc691fda62016-08-12 00:43:1614810 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114811 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014812
14813 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114814 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:4614815 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4014816 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0014817 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014818 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14819 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014820 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4014821 entries, pos,
mikecirone8b85c432016-09-08 19:11:0014822 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14823 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014824
bnc691fda62016-08-12 00:43:1614825 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214826 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014827
14828 EXPECT_TRUE(response->headers->IsKeepAlive());
14829 EXPECT_EQ(200, response->headers->response_code());
14830 EXPECT_EQ(100, response->headers->GetContentLength());
14831 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14832 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714833 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14834 HostPortPair::FromString("myproxy:70")),
14835 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914836 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14837 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14838 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2014839
14840 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614841 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014842 TestLoadTimingNotReusedWithPac(load_timing_info,
14843 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0014844}
14845
rsleevidb16bb02015-11-12 23:47:1714846// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
14847// literal host.
bncd16676a2016-07-20 16:23:0114848TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5914849 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914850 ProxyResolutionService::CreateFixedFromPacResult(
14851 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714852 BoundTestNetLog log;
14853 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914854 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1714855
14856 HttpRequestInfo request;
14857 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1514858 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1014859 request.traffic_annotation =
14860 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714861
14862 // Since we have proxy, should try to establish tunnel.
14863 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1514864 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
14865 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1714866 "Proxy-Connection: keep-alive\r\n\r\n"),
14867
14868 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1514869 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1714870 "Connection: keep-alive\r\n\r\n"),
14871 };
14872
14873 MockRead data_reads1[] = {
14874 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14875
14876 MockRead("HTTP/1.1 200 OK\r\n"),
14877 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14878 MockRead("Content-Length: 100\r\n\r\n"),
14879 MockRead(SYNCHRONOUS, OK),
14880 };
14881
Ryan Sleevib8d7ea02018-05-07 20:01:0114882 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1714883 session_deps_.socket_factory->AddSocketDataProvider(&data1);
14884 SSLSocketDataProvider ssl(ASYNC, OK);
14885 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14886
14887 TestCompletionCallback callback1;
14888
bnc691fda62016-08-12 00:43:1614889 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1714890
bnc691fda62016-08-12 00:43:1614891 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114892 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1714893
14894 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114895 EXPECT_THAT(rv, IsOk());
rsleevidb16bb02015-11-12 23:47:1714896 TestNetLogEntry::List entries;
14897 log.GetEntries(&entries);
14898 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014899 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14900 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1714901 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014902 entries, pos,
14903 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14904 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1714905
bnc691fda62016-08-12 00:43:1614906 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214907 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1714908
14909 EXPECT_TRUE(response->headers->IsKeepAlive());
14910 EXPECT_EQ(200, response->headers->response_code());
14911 EXPECT_EQ(100, response->headers->GetContentLength());
14912 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14913 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714914 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14915 HostPortPair::FromString("myproxy:70")),
14916 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1714917
14918 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614919 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1714920 TestLoadTimingNotReusedWithPac(load_timing_info,
14921 CONNECT_TIMING_HAS_SSL_TIMES);
14922}
14923
[email protected]76a505b2010-08-25 06:23:0014924// Test a basic HTTPS GET request through a proxy, but the server hangs up
14925// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0114926TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4914927 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
14928 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114929 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714930 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014932
[email protected]76a505b2010-08-25 06:23:0014933 HttpRequestInfo request;
14934 request.method = "GET";
bncce36dca22015-04-21 22:11:2314935 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014936 request.traffic_annotation =
14937 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014938
14939 // Since we have proxy, should try to establish tunnel.
14940 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1714941 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14942 "Host: www.example.org:443\r\n"
14943 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014944
rsleevidb16bb02015-11-12 23:47:1714945 MockWrite("GET / HTTP/1.1\r\n"
14946 "Host: www.example.org\r\n"
14947 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014948 };
14949
14950 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0014951 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614952 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0014953 };
14954
Ryan Sleevib8d7ea02018-05-07 20:01:0114955 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714956 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0614957 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0714958 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0014959
[email protected]49639fa2011-12-20 23:22:4114960 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014961
bnc691fda62016-08-12 00:43:1614962 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5014963
bnc691fda62016-08-12 00:43:1614964 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114965 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014966
14967 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114968 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
mmenke43758e62015-05-04 21:09:4614969 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4014970 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0014971 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014972 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14973 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014974 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4014975 entries, pos,
mikecirone8b85c432016-09-08 19:11:0014976 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14977 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014978}
14979
[email protected]749eefa82010-09-13 22:14:0314980// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0114981TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1314982 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4914983 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114984 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0314985
Raul Tambre94493c652019-03-11 17:18:3514986 spdy::SpdySerializedFrame resp(
14987 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314988 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0314989 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114990 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0314991 };
14992
Ryan Sleevib8d7ea02018-05-07 20:01:0114993 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714994 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0314995
[email protected]8ddf8322012-02-23 18:08:0614996 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614997 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0714998 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0314999
danakj1fd259a02016-04-16 03:17:0915000 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315001
15002 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315003 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015004 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115005 PRIVACY_MODE_DISABLED,
15006 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2715007 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215008 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315009
15010 HttpRequestInfo request;
15011 request.method = "GET";
bncce36dca22015-04-21 22:11:2315012 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015013 request.traffic_annotation =
15014 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0315015
bnc691fda62016-08-12 00:43:1615016 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0315017
[email protected]41d64e82013-07-03 22:44:2615018 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015019 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115020 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15021 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0315022}
15023
[email protected]73b8dd222010-11-11 19:55:2415024// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1615025// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0215026void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0715027 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2915028 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715029 request_info.url = GURL("https://www.example.com/");
15030 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915031 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015032 request_info.traffic_annotation =
15033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715034
[email protected]8ddf8322012-02-23 18:08:0615035 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2915036 MockWrite data_writes[] = {
15037 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2415038 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115039 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715040 session_deps_.socket_factory->AddSocketDataProvider(&data);
15041 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2415042
danakj1fd259a02016-04-16 03:17:0915043 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615044 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2415045
[email protected]49639fa2011-12-20 23:22:4115046 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015047 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2915048 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2415049 rv = callback.WaitForResult();
15050 ASSERT_EQ(error, rv);
15051}
15052
bncd16676a2016-07-20 16:23:0115053TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2415054 // Just check a grab bag of cert errors.
15055 static const int kErrors[] = {
15056 ERR_CERT_COMMON_NAME_INVALID,
15057 ERR_CERT_AUTHORITY_INVALID,
15058 ERR_CERT_DATE_INVALID,
15059 };
Avi Drissman4365a4782018-12-28 19:26:2415060 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0615061 CheckErrorIsPassedBack(kErrors[i], ASYNC);
15062 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2415063 }
15064}
15065
[email protected]bd0b6772011-01-11 19:59:3015066// Ensure that a client certificate is removed from the SSL client auth
15067// cache when:
15068// 1) No proxy is involved.
15069// 2) TLS False Start is disabled.
15070// 3) The initial TLS handshake requests a client certificate.
15071// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115072TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915073 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715074 request_info.url = GURL("https://www.example.com/");
15075 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915076 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015077 request_info.traffic_annotation =
15078 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715079
[email protected]bd0b6772011-01-11 19:59:3015080 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4115081 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015082
15083 // [ssl_]data1 contains the data for the first SSL handshake. When a
15084 // CertificateRequest is received for the first time, the handshake will
15085 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2915086 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015087 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715088 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115089 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715090 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015091
15092 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
15093 // False Start is not being used, the result of the SSL handshake will be
15094 // returned as part of the SSLClientSocket::Connect() call. This test
15095 // matches the result of a server sending a handshake_failure alert,
15096 // rather than a Finished message, because it requires a client
15097 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2915098 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3015099 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715100 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0115101 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0715102 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015103
15104 // [ssl_]data3 contains the data for the third SSL handshake. When a
15105 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1315106 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
15107 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3015108 // of the HttpNetworkTransaction. Because this test failure is due to
15109 // requiring a client certificate, this fallback handshake should also
15110 // fail.
ttuttle859dc7a2015-04-23 19:42:2915111 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1315112 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3015113 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715114 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115115 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0715116 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015117
[email protected]80c75f682012-05-26 16:22:1715118 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
15119 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4215120 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
15121 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1715122 // of the HttpNetworkTransaction. Because this test failure is due to
15123 // requiring a client certificate, this fallback handshake should also
15124 // fail.
ttuttle859dc7a2015-04-23 19:42:2915125 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1715126 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715127 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115128 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0715129 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715130
danakj1fd259a02016-04-16 03:17:0915131 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615132 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015133
[email protected]bd0b6772011-01-11 19:59:3015134 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4115135 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015136 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115137 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015138
15139 // Complete the SSL handshake, which should abort due to requiring a
15140 // client certificate.
15141 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115142 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015143
15144 // Indicate that no certificate should be supplied. From the perspective
15145 // of SSLClientCertCache, NULL is just as meaningful as a real
15146 // certificate, so this is the same as supply a
15147 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515148 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115149 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015150
15151 // Ensure the certificate was added to the client auth cache before
15152 // allowing the connection to continue restarting.
15153 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415154 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4115155 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415156 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215157 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015158
15159 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715160 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15161 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015162 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115163 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015164
15165 // Ensure that the client certificate is removed from the cache on a
15166 // handshake failure.
[email protected]791879c2013-12-17 07:22:4115167 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415168 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015169}
15170
15171// Ensure that a client certificate is removed from the SSL client auth
15172// cache when:
15173// 1) No proxy is involved.
15174// 2) TLS False Start is enabled.
15175// 3) The initial TLS handshake requests a client certificate.
15176// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115177TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915178 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715179 request_info.url = GURL("https://www.example.com/");
15180 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915181 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015182 request_info.traffic_annotation =
15183 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715184
[email protected]bd0b6772011-01-11 19:59:3015185 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4115186 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015187
15188 // When TLS False Start is used, SSLClientSocket::Connect() calls will
15189 // return successfully after reading up to the peer's Certificate message.
15190 // This is to allow the caller to call SSLClientSocket::Write(), which can
15191 // enqueue application data to be sent in the same packet as the
15192 // ChangeCipherSpec and Finished messages.
15193 // The actual handshake will be finished when SSLClientSocket::Read() is
15194 // called, which expects to process the peer's ChangeCipherSpec and
15195 // Finished messages. If there was an error negotiating with the peer,
15196 // such as due to the peer requiring a client certificate when none was
15197 // supplied, the alert sent by the peer won't be processed until Read() is
15198 // called.
15199
15200 // Like the non-False Start case, when a client certificate is requested by
15201 // the peer, the handshake is aborted during the Connect() call.
15202 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2915203 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015204 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715205 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115206 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715207 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015208
15209 // When a client certificate is supplied, Connect() will not be aborted
15210 // when the peer requests the certificate. Instead, the handshake will
15211 // artificially succeed, allowing the caller to write the HTTP request to
15212 // the socket. The handshake messages are not processed until Read() is
15213 // called, which then detects that the handshake was aborted, due to the
15214 // peer sending a handshake_failure because it requires a client
15215 // certificate.
ttuttle859dc7a2015-04-23 19:42:2915216 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015217 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715218 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2915219 MockRead data2_reads[] = {
15220 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3015221 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115222 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715223 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015224
15225 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1715226 // the data for the SSL handshake once the TLSv1.1 connection falls back to
15227 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915228 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015229 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715230 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115231 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715232 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015233
[email protected]80c75f682012-05-26 16:22:1715234 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
15235 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915236 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1715237 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715238 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115239 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715240 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715241
[email protected]7799de12013-05-30 05:52:5115242 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2915243 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5115244 ssl_data5.cert_request_info = cert_request.get();
15245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0115246 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5115247 session_deps_.socket_factory->AddSocketDataProvider(&data5);
15248
danakj1fd259a02016-04-16 03:17:0915249 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615250 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015251
[email protected]bd0b6772011-01-11 19:59:3015252 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4115253 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015254 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115255 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015256
15257 // Complete the SSL handshake, which should abort due to requiring a
15258 // client certificate.
15259 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115260 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015261
15262 // Indicate that no certificate should be supplied. From the perspective
15263 // of SSLClientCertCache, NULL is just as meaningful as a real
15264 // certificate, so this is the same as supply a
15265 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515266 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115267 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015268
15269 // Ensure the certificate was added to the client auth cache before
15270 // allowing the connection to continue restarting.
15271 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415272 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4115273 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415274 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215275 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015276
[email protected]bd0b6772011-01-11 19:59:3015277 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715278 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15279 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015280 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115281 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015282
15283 // Ensure that the client certificate is removed from the cache on a
15284 // handshake failure.
[email protected]791879c2013-12-17 07:22:4115285 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415286 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015287}
15288
[email protected]8c405132011-01-11 22:03:1815289// Ensure that a client certificate is removed from the SSL client auth
15290// cache when:
15291// 1) An HTTPS proxy is involved.
15292// 3) The HTTPS proxy requests a client certificate.
15293// 4) The client supplies an invalid/unacceptable certificate for the
15294// proxy.
bncd16676a2016-07-20 16:23:0115295TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4915296 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15297 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115298 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715299 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1815300
David Benjamin3b94b0f2019-04-25 23:07:5215301 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115302 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1815303
David Benjamin3b94b0f2019-04-25 23:07:5215304 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
15305 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2915306 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1815307 requests[0].url = GURL("https://www.example.com/");
15308 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915309 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015310 requests[0].traffic_annotation =
15311 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815312
David Benjamin3b94b0f2019-04-25 23:07:5215313 // HTTPS requests are tunneled.
15314 MockWrite https_writes[] = {
15315 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
15316 "Host: www.example.com:443\r\n"
15317 "Proxy-Connection: keep-alive\r\n\r\n"),
15318 };
15319
[email protected]8c405132011-01-11 22:03:1815320 requests[1].url = GURL("http://www.example.com/");
15321 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915322 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015323 requests[1].traffic_annotation =
15324 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815325
David Benjamin3b94b0f2019-04-25 23:07:5215326 // HTTP requests are not.
15327 MockWrite http_writes[] = {
15328 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
15329 "Host: www.example.com\r\n"
15330 "Proxy-Connection: keep-alive\r\n\r\n"),
15331 };
[email protected]8c405132011-01-11 22:03:1815332
David Benjamin3b94b0f2019-04-25 23:07:5215333 // When the server rejects the client certificate, it will close the
15334 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
15335 // TLS 1.2 with False Start), the error is returned out of the first Read().
15336 for (bool reject_in_connect : {true, false}) {
15337 SCOPED_TRACE(reject_in_connect);
15338 // Client certificate errors are typically signaled with
15339 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
15340 // protocol error.
15341 for (Error reject_error :
15342 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
15343 SCOPED_TRACE(reject_error);
15344 // Tunneled and non-tunneled requests are handled differently. Test both.
15345 for (const HttpRequestInfo& request : requests) {
15346 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1815347
David Benjamin3b94b0f2019-04-25 23:07:5215348 session_deps_.socket_factory =
15349 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1815350
David Benjamin3b94b0f2019-04-25 23:07:5215351 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
15352 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
15353 // for proxies. Rather than represending the endpoint
15354 // (www.example.com:443), they represent failures with the HTTPS proxy
15355 // (proxy:70).
15356 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
15357 ssl_data1.cert_request_info = cert_request.get();
15358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15359 StaticSocketDataProvider data1;
15360 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1815361
David Benjamin3b94b0f2019-04-25 23:07:5215362 base::Optional<SSLSocketDataProvider> ssl_data2;
15363 base::Optional<StaticSocketDataProvider> data2;
15364 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
15365 if (reject_in_connect) {
15366 ssl_data2.emplace(ASYNC, reject_error);
15367 // There are no reads or writes.
15368 data2.emplace();
15369 } else {
15370 ssl_data2.emplace(ASYNC, OK);
15371 // We will get one Write() in before observing the error in Read().
15372 if (request.url.SchemeIsCryptographic()) {
15373 data2.emplace(error_in_read, https_writes);
15374 } else {
15375 data2.emplace(error_in_read, http_writes);
15376 }
15377 }
15378 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1815379
David Benjamin3b94b0f2019-04-25 23:07:5215380 session_deps_.socket_factory->AddSSLSocketDataProvider(
15381 &ssl_data2.value());
15382 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1815383
David Benjamin3b94b0f2019-04-25 23:07:5215384 std::unique_ptr<HttpNetworkSession> session =
15385 CreateSession(&session_deps_);
15386 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15387
15388 // Begin the SSL handshake with the proxy.
15389 TestCompletionCallback callback;
15390 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15391 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15392
15393 // Complete the SSL handshake, which should abort due to requiring a
15394 // client certificate.
15395 rv = callback.WaitForResult();
15396 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15397
15398 // Indicate that no certificate should be supplied. From the
15399 // perspective of SSLClientCertCache, NULL is just as meaningful as a
15400 // real certificate, so this is the same as supply a
15401 // legitimate-but-unacceptable certificate.
15402 rv =
15403 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
15404 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15405
15406 // Ensure the certificate was added to the client auth cache before
15407 // allowing the connection to continue restarting.
15408 scoped_refptr<X509Certificate> client_cert;
15409 scoped_refptr<SSLPrivateKey> client_private_key;
15410 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
15411 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15412 ASSERT_FALSE(client_cert);
15413 // Ensure the certificate was NOT cached for the endpoint. This only
15414 // applies to HTTPS requests, but is fine to check for HTTP requests.
15415 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15416 HostPortPair("www.example.com", 443), &client_cert,
15417 &client_private_key));
15418
15419 // Restart the handshake. This will consume ssl_data2. The result code
15420 // is checked against what ssl_data2 should return.
15421 rv = callback.WaitForResult();
15422 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
15423 IsError(reject_error)));
15424
15425 // Now that the new handshake has failed, ensure that the client
15426 // certificate was removed from the client auth cache.
15427 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15428 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15429 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15430 HostPortPair("www.example.com", 443), &client_cert,
15431 &client_private_key));
15432 }
15433 }
[email protected]8c405132011-01-11 22:03:1815434 }
15435}
15436
bncd16676a2016-07-20 16:23:0115437TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4615438 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915439 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915440 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615441
bnc032658ba2016-09-26 18:17:1515442 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615443
Ryan Hamilton0239aac2018-05-19 00:03:1315444 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915445 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815446 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315447 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715448 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615449 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115450 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615451 };
Ryan Hamilton0239aac2018-05-19 00:03:1315452 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515453 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315454 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115455 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315456 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515457 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315458 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115459 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615460 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115461 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15462 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315463 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615464 };
15465
eroman36d84e54432016-03-17 03:23:0215466 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215467 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115468 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715469 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615470
[email protected]aa22b242011-11-16 18:58:2915471 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615472 HttpRequestInfo request1;
15473 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315474 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615475 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015476 request1.traffic_annotation =
15477 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015478 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615479
tfarina42834112016-09-22 13:38:2015480 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115481 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15482 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615483
15484 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215485 ASSERT_TRUE(response);
15486 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215487 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615488
15489 std::string response_data;
robpercival214763f2016-07-01 23:27:0115490 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615491 EXPECT_EQ("hello!", response_data);
15492
bnca4d611d2016-09-22 19:55:3715493 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315494 rv = session_deps_.host_resolver->LoadIntoCache(
15495 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0115496 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4615497
15498 HttpRequestInfo request2;
15499 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715500 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4615501 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015502 request2.traffic_annotation =
15503 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015504 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615505
tfarina42834112016-09-22 13:38:2015506 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115507 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15508 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615509
15510 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215511 ASSERT_TRUE(response);
15512 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215513 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615514 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215515 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115516 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615517 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4615518}
15519
bncd16676a2016-07-20 16:23:0115520TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0215521 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915522 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915523 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0215524
bnc032658ba2016-09-26 18:17:1515525 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0215526
Ryan Hamilton0239aac2018-05-19 00:03:1315527 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915528 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815529 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315530 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715531 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0215532 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115533 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0215534 };
Ryan Hamilton0239aac2018-05-19 00:03:1315535 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515536 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315537 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115538 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315539 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515540 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315541 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115542 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0215543 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115544 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15545 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315546 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0215547 };
15548
eroman36d84e54432016-03-17 03:23:0215549 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215550 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115551 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715552 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0215553
15554 TestCompletionCallback callback;
15555 HttpRequestInfo request1;
15556 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315557 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0215558 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015559 request1.traffic_annotation =
15560 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015561 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215562
tfarina42834112016-09-22 13:38:2015563 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115564 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15565 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215566
15567 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215568 ASSERT_TRUE(response);
15569 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215570 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215571
15572 std::string response_data;
robpercival214763f2016-07-01 23:27:0115573 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215574 EXPECT_EQ("hello!", response_data);
15575
15576 HttpRequestInfo request2;
15577 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715578 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0215579 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015580 request2.traffic_annotation =
15581 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015582 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215583
tfarina42834112016-09-22 13:38:2015584 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115585 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15586 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215587
15588 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215589 ASSERT_TRUE(response);
15590 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215591 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215592 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215593 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115594 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215595 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0215596}
15597
bnc8016c1f2017-03-31 02:11:2915598// Regression test for https://crbug.com/546991.
15599// The server might not be able to serve an IP pooled request, and might send a
15600// 421 Misdirected Request response status to indicate this.
15601// HttpNetworkTransaction should reset the request and retry without IP pooling.
15602TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
15603 // Two hosts resolve to the same IP address.
15604 const std::string ip_addr = "1.2.3.4";
15605 IPAddress ip;
15606 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15607 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15608
Jeremy Roman0579ed62017-08-29 15:56:1915609 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2915610 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15611 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15612
15613 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15614
15615 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315616 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2915617 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15618 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315619 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2915620 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315621 spdy::SpdySerializedFrame rst(
15622 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2915623 MockWrite writes1[] = {
15624 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15625 CreateMockWrite(rst, 6),
15626 };
15627
15628 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315629 spdy::SpdySerializedFrame resp1(
15630 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15631 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15632 spdy::SpdyHeaderBlock response_headers;
15633 response_headers[spdy::kHttp2StatusHeader] = "421";
15634 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2915635 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
15636 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15637 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15638
15639 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115640 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2915641 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15642
15643 AddSSLSocketData();
15644
15645 // Retry the second request on a second connection.
15646 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315647 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2915648 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15649 MockWrite writes2[] = {
15650 CreateMockWrite(req3, 0),
15651 };
15652
Ryan Hamilton0239aac2018-05-19 00:03:1315653 spdy::SpdySerializedFrame resp3(
15654 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
15655 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2915656 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15657 MockRead(ASYNC, 0, 3)};
15658
15659 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115660 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2915661 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15662
15663 AddSSLSocketData();
15664
15665 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315666 int rv = session_deps_.host_resolver->LoadIntoCache(
15667 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2915668 EXPECT_THAT(rv, IsOk());
15669
15670 HttpRequestInfo request1;
15671 request1.method = "GET";
15672 request1.url = GURL("https://www.example.org/");
15673 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015674 request1.traffic_annotation =
15675 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915676 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15677
Eric Orthf4db66a2019-02-19 21:35:3315678 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2915679 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15680 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15681 rv = callback.WaitForResult();
15682 EXPECT_THAT(rv, IsOk());
15683
15684 const HttpResponseInfo* response = trans1.GetResponseInfo();
15685 ASSERT_TRUE(response);
15686 ASSERT_TRUE(response->headers);
15687 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15688 EXPECT_TRUE(response->was_fetched_via_spdy);
15689 EXPECT_TRUE(response->was_alpn_negotiated);
15690 std::string response_data;
15691 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
15692 EXPECT_EQ("hello!", response_data);
15693
15694 HttpRequestInfo request2;
15695 request2.method = "GET";
15696 request2.url = GURL("https://mail.example.org/");
15697 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015698 request2.traffic_annotation =
15699 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915700 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
15701
15702 BoundTestNetLog log;
15703 rv = trans2.Start(&request2, callback.callback(), log.bound());
15704 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15705 rv = callback.WaitForResult();
15706 EXPECT_THAT(rv, IsOk());
15707
15708 response = trans2.GetResponseInfo();
15709 ASSERT_TRUE(response);
15710 ASSERT_TRUE(response->headers);
15711 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15712 EXPECT_TRUE(response->was_fetched_via_spdy);
15713 EXPECT_TRUE(response->was_alpn_negotiated);
15714 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
15715 EXPECT_EQ("hello!", response_data);
15716
15717 TestNetLogEntry::List entries;
15718 log.GetEntries(&entries);
davidbence688ae2017-05-04 15:12:5915719 ExpectLogContainsSomewhere(
15720 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2915721 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5915722}
15723
15724// Test that HTTP 421 responses are properly returned to the caller if received
15725// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
15726// portions of the response.
15727TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
15728 // Two hosts resolve to the same IP address.
15729 const std::string ip_addr = "1.2.3.4";
15730 IPAddress ip;
15731 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15732 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15733
Jeremy Roman0579ed62017-08-29 15:56:1915734 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5915735 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15736 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15737
15738 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15739
15740 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315741 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5915742 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15743 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315744 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5915745 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315746 spdy::SpdySerializedFrame rst(
15747 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5915748 MockWrite writes1[] = {
15749 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15750 CreateMockWrite(rst, 6),
15751 };
15752
15753 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315754 spdy::SpdySerializedFrame resp1(
15755 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15756 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15757 spdy::SpdyHeaderBlock response_headers;
15758 response_headers[spdy::kHttp2StatusHeader] = "421";
15759 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5915760 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
15761 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15762 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15763
15764 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115765 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5915766 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15767
15768 AddSSLSocketData();
15769
15770 // Retry the second request on a second connection. It returns 421 Misdirected
15771 // Retry again.
15772 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315773 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5915774 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15775 MockWrite writes2[] = {
15776 CreateMockWrite(req3, 0),
15777 };
15778
Ryan Hamilton0239aac2018-05-19 00:03:1315779 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5915780 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1315781 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5915782 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15783 MockRead(ASYNC, 0, 3)};
15784
15785 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115786 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5915787 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15788
15789 AddSSLSocketData();
15790
15791 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315792 int rv = session_deps_.host_resolver->LoadIntoCache(
15793 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5915794 EXPECT_THAT(rv, IsOk());
15795
15796 HttpRequestInfo request1;
15797 request1.method = "GET";
15798 request1.url = GURL("https://www.example.org/");
15799 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015800 request1.traffic_annotation =
15801 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5915802 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15803
Eric Orthf4db66a2019-02-19 21:35:3315804 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5915805 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15806 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15807 rv = callback.WaitForResult();
15808 EXPECT_THAT(rv, IsOk());
15809
15810 const HttpResponseInfo* response = trans1.GetResponseInfo();
15811 ASSERT_TRUE(response);
15812 ASSERT_TRUE(response->headers);
15813 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15814 EXPECT_TRUE(response->was_fetched_via_spdy);
15815 EXPECT_TRUE(response->was_alpn_negotiated);
15816 std::string response_data;
15817 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
15818 EXPECT_EQ("hello!", response_data);
15819
15820 HttpRequestInfo request2;
15821 request2.method = "GET";
15822 request2.url = GURL("https://mail.example.org/");
15823 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015824 request2.traffic_annotation =
15825 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5915826 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
15827
15828 BoundTestNetLog log;
15829 rv = trans2.Start(&request2, callback.callback(), log.bound());
15830 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15831 rv = callback.WaitForResult();
15832 EXPECT_THAT(rv, IsOk());
15833
15834 // After a retry, the 421 Misdirected Request is reported back up to the
15835 // caller.
15836 response = trans2.GetResponseInfo();
15837 ASSERT_TRUE(response);
15838 ASSERT_TRUE(response->headers);
15839 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
15840 EXPECT_TRUE(response->was_fetched_via_spdy);
15841 EXPECT_TRUE(response->was_alpn_negotiated);
15842 EXPECT_TRUE(response->ssl_info.cert);
15843 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
15844 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2915845}
15846
bncd16676a2016-07-20 16:23:0115847TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1315848 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3415849 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
15850 session_deps_.host_resolver =
15851 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0915852 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615853
bnc032658ba2016-09-26 18:17:1515854 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615855
Ryan Hamilton0239aac2018-05-19 00:03:1315856 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915857 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815858 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315859 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715860 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615861 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115862 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615863 };
Ryan Hamilton0239aac2018-05-19 00:03:1315864 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515865 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315866 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115867 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315868 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515869 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315870 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115871 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615872 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115873 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15874 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315875 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615876 };
15877
eroman36d84e54432016-03-17 03:23:0215878 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215879 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115880 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715881 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615882
[email protected]aa22b242011-11-16 18:58:2915883 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615884 HttpRequestInfo request1;
15885 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315886 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615887 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015888 request1.traffic_annotation =
15889 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015890 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615891
tfarina42834112016-09-22 13:38:2015892 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115893 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15894 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615895
15896 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215897 ASSERT_TRUE(response);
15898 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215899 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615900
15901 std::string response_data;
robpercival214763f2016-07-01 23:27:0115902 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615903 EXPECT_EQ("hello!", response_data);
15904
15905 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315906 rv = session_deps_.host_resolver->LoadIntoCache(
15907 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0115908 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4615909
15910 HttpRequestInfo request2;
15911 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715912 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4615913 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015914 request2.traffic_annotation =
15915 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015916 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615917
tfarina42834112016-09-22 13:38:2015918 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15920 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615921
15922 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215923 ASSERT_TRUE(response);
15924 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215925 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615926 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215927 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115928 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615929 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4615930}
15931
bncd16676a2016-07-20 16:23:0115932TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2315933 const std::string https_url = "https://www.example.org:8080/";
15934 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0415935
15936 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1315937 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4915938 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0415939
15940 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4115941 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0415942 };
15943
Raul Tambre94493c652019-03-11 17:18:3515944 spdy::SpdySerializedFrame resp1(
15945 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315946 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4115947 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5915948 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0415949
Ryan Sleevib8d7ea02018-05-07 20:01:0115950 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0415951 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5715952 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0415953
15954 // HTTP GET for the HTTP URL
15955 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1315956 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3415957 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315958 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3415959 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0415960 };
15961
15962 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1315963 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
15964 MockRead(ASYNC, 2, "hello"),
15965 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0415966 };
15967
Ryan Sleevib8d7ea02018-05-07 20:01:0115968 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0415969
[email protected]8450d722012-07-02 19:14:0415970 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615971 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715972 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15973 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15974 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0415975
danakj1fd259a02016-04-16 03:17:0915976 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0415977
15978 // Start the first transaction to set up the SpdySession
15979 HttpRequestInfo request1;
15980 request1.method = "GET";
15981 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0415982 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015983 request1.traffic_annotation =
15984 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015985 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0415986 TestCompletionCallback callback1;
15987 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2015988 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5515989 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0415990
robpercival214763f2016-07-01 23:27:0115991 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0415992 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
15993
15994 // Now, start the HTTP request
15995 HttpRequestInfo request2;
15996 request2.method = "GET";
15997 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0415998 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015999 request2.traffic_annotation =
16000 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016001 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416002 TestCompletionCallback callback2;
16003 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016004 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516005 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416006
robpercival214763f2016-07-01 23:27:0116007 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416008 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16009}
16010
bnc5452e2a2015-05-08 16:27:4216011// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
16012// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0116013TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2516014 url::SchemeHostPort server("https", "www.example.org", 443);
16015 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4216016
bnc8bef8da22016-05-30 01:28:2516017 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4216018 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616019 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216020 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16021
16022 // No data should be read from the alternative, because HTTP/1.1 is
16023 // negotiated.
16024 StaticSocketDataProvider data;
16025 session_deps_.socket_factory->AddSocketDataProvider(&data);
16026
16027 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4616028 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4216029 // mocked. This way the request relies on the alternate Job.
16030 StaticSocketDataProvider data_refused;
16031 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16032 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16033
zhongyi3d4a55e72016-04-22 20:36:4616034 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016036 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216037 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116038 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216039 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116040 http_server_properties->SetHttp2AlternativeService(
16041 server, alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216042
bnc5452e2a2015-05-08 16:27:4216043 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4616044 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216045 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2516046 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1016047 request.traffic_annotation =
16048 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216049 TestCompletionCallback callback;
16050
16051 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5216052 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2016053 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5216054 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4216055}
16056
bnc40448a532015-05-11 19:13:1416057// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4616058// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1416059// succeeds, the request should succeed, even if the latter fails because
16060// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0116061TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2516062 url::SchemeHostPort server("https", "www.example.org", 443);
16063 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1416064
16065 // Negotiate HTTP/1.1 with alternative.
16066 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616067 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416068 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
16069
16070 // No data should be read from the alternative, because HTTP/1.1 is
16071 // negotiated.
16072 StaticSocketDataProvider data;
16073 session_deps_.socket_factory->AddSocketDataProvider(&data);
16074
zhongyi3d4a55e72016-04-22 20:36:4616075 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1416076 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616077 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416078 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
16079
16080 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2516081 MockWrite("GET / HTTP/1.1\r\n"
16082 "Host: www.example.org\r\n"
16083 "Connection: keep-alive\r\n\r\n"),
16084 MockWrite("GET /second HTTP/1.1\r\n"
16085 "Host: www.example.org\r\n"
16086 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1416087 };
16088
16089 MockRead http_reads[] = {
16090 MockRead("HTTP/1.1 200 OK\r\n"),
16091 MockRead("Content-Type: text/html\r\n"),
16092 MockRead("Content-Length: 6\r\n\r\n"),
16093 MockRead("foobar"),
16094 MockRead("HTTP/1.1 200 OK\r\n"),
16095 MockRead("Content-Type: text/html\r\n"),
16096 MockRead("Content-Length: 7\r\n\r\n"),
16097 MockRead("another"),
16098 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116099 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1416100 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16101
zhongyi3d4a55e72016-04-22 20:36:4616102 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916103 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016104 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1416105 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116106 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216107 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116108 http_server_properties->SetHttp2AlternativeService(
16109 server, alternative_service, expiration);
bnc40448a532015-05-11 19:13:1416110
16111 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16112 HttpRequestInfo request1;
16113 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2516114 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1416115 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016116 request1.traffic_annotation =
16117 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416118 TestCompletionCallback callback1;
16119
tfarina42834112016-09-22 13:38:2016120 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416121 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116122 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416123
16124 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216125 ASSERT_TRUE(response1);
16126 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1416127 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
16128
16129 std::string response_data1;
robpercival214763f2016-07-01 23:27:0116130 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1416131 EXPECT_EQ("foobar", response_data1);
16132
16133 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
16134 // for alternative service.
16135 EXPECT_TRUE(
16136 http_server_properties->IsAlternativeServiceBroken(alternative_service));
16137
zhongyi3d4a55e72016-04-22 20:36:4616138 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1416139 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4616140 // to server.
bnc40448a532015-05-11 19:13:1416141 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16142 HttpRequestInfo request2;
16143 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2516144 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1416145 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016146 request2.traffic_annotation =
16147 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416148 TestCompletionCallback callback2;
16149
tfarina42834112016-09-22 13:38:2016150 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416151 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116152 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416153
16154 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216155 ASSERT_TRUE(response2);
16156 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1416157 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
16158
16159 std::string response_data2;
robpercival214763f2016-07-01 23:27:0116160 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1416161 EXPECT_EQ("another", response_data2);
16162}
16163
bnc5452e2a2015-05-08 16:27:4216164// Alternative service requires HTTP/2 (or SPDY), but there is already a
16165// HTTP/1.1 socket open to the alternative server. That socket should not be
16166// used.
bncd16676a2016-07-20 16:23:0116167TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4616168 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4216169 HostPortPair alternative("alternative.example.org", 443);
16170 std::string origin_url = "https://origin.example.org:443";
16171 std::string alternative_url = "https://alternative.example.org:443";
16172
16173 // Negotiate HTTP/1.1 with alternative.example.org.
16174 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616175 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216176 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16177
16178 // HTTP/1.1 data for |request1| and |request2|.
16179 MockWrite http_writes[] = {
16180 MockWrite(
16181 "GET / HTTP/1.1\r\n"
16182 "Host: alternative.example.org\r\n"
16183 "Connection: keep-alive\r\n\r\n"),
16184 MockWrite(
16185 "GET / HTTP/1.1\r\n"
16186 "Host: alternative.example.org\r\n"
16187 "Connection: keep-alive\r\n\r\n"),
16188 };
16189
16190 MockRead http_reads[] = {
16191 MockRead(
16192 "HTTP/1.1 200 OK\r\n"
16193 "Content-Type: text/html; charset=iso-8859-1\r\n"
16194 "Content-Length: 40\r\n\r\n"
16195 "first HTTP/1.1 response from alternative"),
16196 MockRead(
16197 "HTTP/1.1 200 OK\r\n"
16198 "Content-Type: text/html; charset=iso-8859-1\r\n"
16199 "Content-Length: 41\r\n\r\n"
16200 "second HTTP/1.1 response from alternative"),
16201 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116202 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4216203 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16204
16205 // This test documents that an alternate Job should not pool to an already
16206 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4616207 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4216208 StaticSocketDataProvider data_refused;
16209 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16210 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16211
zhongyi3d4a55e72016-04-22 20:36:4616212 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916213 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016214 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216215 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116216 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216217 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116218 http_server_properties->SetHttp2AlternativeService(
16219 server, alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216220
16221 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4216222 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4616223 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216224 request1.method = "GET";
16225 request1.url = GURL(alternative_url);
16226 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016227 request1.traffic_annotation =
16228 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216229 TestCompletionCallback callback1;
16230
tfarina42834112016-09-22 13:38:2016231 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116232 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616233 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216234 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5216235 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4216236 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216237 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216238 EXPECT_FALSE(response1->was_fetched_via_spdy);
16239 std::string response_data1;
bnc691fda62016-08-12 00:43:1616240 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4216241 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
16242
16243 // Request for origin.example.org, which has an alternative service. This
16244 // will start two Jobs: the alternative looks for connections to pool to,
16245 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4616246 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4216247 // this request fails.
bnc5452e2a2015-05-08 16:27:4216248 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4616249 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216250 request2.method = "GET";
16251 request2.url = GURL(origin_url);
16252 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016253 request2.traffic_annotation =
16254 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216255 TestCompletionCallback callback2;
16256
tfarina42834112016-09-22 13:38:2016257 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116258 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4216259
16260 // Another transaction to alternative. This is to test that the HTTP/1.1
16261 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4216262 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4616263 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216264 request3.method = "GET";
16265 request3.url = GURL(alternative_url);
16266 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016267 request3.traffic_annotation =
16268 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216269 TestCompletionCallback callback3;
16270
tfarina42834112016-09-22 13:38:2016271 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116272 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616273 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216274 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5216275 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4216276 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216277 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216278 EXPECT_FALSE(response3->was_fetched_via_spdy);
16279 std::string response_data3;
bnc691fda62016-08-12 00:43:1616280 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4216281 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
16282}
16283
bncd16676a2016-07-20 16:23:0116284TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2316285 const std::string https_url = "https://www.example.org:8080/";
16286 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416287
rdsmithebb50aa2015-11-12 03:44:3816288 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0116289 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3816290
[email protected]8450d722012-07-02 19:14:0416291 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2316292 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0416293 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
16294 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
16295 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1316296 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916297 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316298 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0216299 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3916300
16301 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1316302 spdy::SpdyHeaderBlock req2_block;
16303 req2_block[spdy::kHttp2MethodHeader] = "GET";
16304 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
16305 req2_block[spdy::kHttp2SchemeHeader] = "http";
16306 req2_block[spdy::kHttp2PathHeader] = "/";
16307 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1516308 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0416309
16310 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116311 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
16312 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0416313 };
16314
Ryan Hamilton0239aac2018-05-19 00:03:1316315 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1516316 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316317 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1516318 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316319 spdy::SpdySerializedFrame body1(
16320 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
16321 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3816322 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316323 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3816324 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3516325 spdy::SpdySerializedFrame resp2(
16326 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316327 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3316328 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116329 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3316330 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4116331 CreateMockRead(wrapped_resp1, 4),
16332 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3316333 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4116334 CreateMockRead(resp2, 8),
16335 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3316336 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
16337 };
[email protected]8450d722012-07-02 19:14:0416338
Ryan Sleevib8d7ea02018-05-07 20:01:0116339 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416340 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716341 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416342
Lily Houghton8c2f97d2018-01-22 05:06:5916343 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4916344 ProxyResolutionService::CreateFixedFromPacResult(
16345 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116346 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716347 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0416348 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616349 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316350 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0416351 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616352 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316353 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16354 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0416355
danakj1fd259a02016-04-16 03:17:0916356 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0416357
16358 // Start the first transaction to set up the SpdySession
16359 HttpRequestInfo request1;
16360 request1.method = "GET";
16361 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416362 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016363 request1.traffic_annotation =
16364 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016365 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416366 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2016367 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416368
mmenke666a6fea2015-12-19 04:16:3316369 // This pause is a hack to avoid running into https://crbug.com/497228.
16370 data1.RunUntilPaused();
16371 base::RunLoop().RunUntilIdle();
16372 data1.Resume();
robpercival214763f2016-07-01 23:27:0116373 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0416374 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16375
[email protected]f6c63db52013-02-02 00:35:2216376 LoadTimingInfo load_timing_info1;
16377 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
16378 TestLoadTimingNotReusedWithPac(load_timing_info1,
16379 CONNECT_TIMING_HAS_SSL_TIMES);
16380
mmenke666a6fea2015-12-19 04:16:3316381 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0416382 HttpRequestInfo request2;
16383 request2.method = "GET";
16384 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416385 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016386 request2.traffic_annotation =
16387 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016388 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416389 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2016390 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416391
mmenke666a6fea2015-12-19 04:16:3316392 // This pause is a hack to avoid running into https://crbug.com/497228.
16393 data1.RunUntilPaused();
16394 base::RunLoop().RunUntilIdle();
16395 data1.Resume();
robpercival214763f2016-07-01 23:27:0116396 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3316397
[email protected]8450d722012-07-02 19:14:0416398 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2216399
16400 LoadTimingInfo load_timing_info2;
16401 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
16402 // The established SPDY sessions is considered reused by the HTTP request.
16403 TestLoadTimingReusedWithPac(load_timing_info2);
16404 // HTTP requests over a SPDY session should have a different connection
16405 // socket_log_id than requests over a tunnel.
16406 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0416407}
16408
[email protected]2d88e7d2012-07-19 17:55:1716409// Test that in the case where we have a SPDY session to a SPDY proxy
16410// that we do not pool other origins that resolve to the same IP when
16411// the certificate does not match the new origin.
16412// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0116413TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2316414 const std::string url1 = "http://www.example.org/";
16415 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1716416 const std::string ip_addr = "1.2.3.4";
16417
rdsmithebb50aa2015-11-12 03:44:3816418 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0116419 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3816420
[email protected]2d88e7d2012-07-19 17:55:1716421 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1316422 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2316423 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1316424 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1516425 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1716426
16427 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116428 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1716429 };
16430
Raul Tambre94493c652019-03-11 17:18:3516431 spdy::SpdySerializedFrame resp1(
16432 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316433 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1716434 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116435 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
16436 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1716437 };
16438
Ryan Sleevib8d7ea02018-05-07 20:01:0116439 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3216440 IPAddress ip;
martijn654c8c42016-02-10 22:10:5916441 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1716442 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16443 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3316444 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1716445
16446 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1316447 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916448 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1716449
16450 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116451 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1716452 };
16453
Ryan Hamilton0239aac2018-05-19 00:03:1316454 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3516455 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316456 spdy::SpdySerializedFrame body2(
16457 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116458 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3316459 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1716460
Ryan Sleevib8d7ea02018-05-07 20:01:0116461 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1716462 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3316463 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1716464
16465 // Set up a proxy config that sends HTTP requests to a proxy, and
16466 // all others direct.
16467 ProxyConfig proxy_config;
16468 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4916469 session_deps_.proxy_resolution_service =
16470 std::make_unique<ProxyResolutionService>(
16471 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
16472 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
16473 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1716474
bncce36dca22015-04-21 22:11:2316475 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616476 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1716477 // Load a valid cert. Note, that this does not need to
16478 // be valid for proxy because the MockSSLClientSocket does
16479 // not actually verify it. But SpdySession will use this
16480 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4916481 ssl1.ssl_info.cert =
16482 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
16483 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3316484 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16485 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1716486
16487 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616488 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16490 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1716491
Jeremy Roman0579ed62017-08-29 15:56:1916492 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2316493 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0716494 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1716495
danakj1fd259a02016-04-16 03:17:0916496 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1716497
16498 // Start the first transaction to set up the SpdySession
16499 HttpRequestInfo request1;
16500 request1.method = "GET";
16501 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1716502 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016503 request1.traffic_annotation =
16504 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016505 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716506 TestCompletionCallback callback1;
16507 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016508 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3316509 // This pause is a hack to avoid running into https://crbug.com/497228.
16510 data1.RunUntilPaused();
16511 base::RunLoop().RunUntilIdle();
16512 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1716513
robpercival214763f2016-07-01 23:27:0116514 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716515 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16516
16517 // Now, start the HTTP request
16518 HttpRequestInfo request2;
16519 request2.method = "GET";
16520 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1716521 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016522 request2.traffic_annotation =
16523 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016524 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716525 TestCompletionCallback callback2;
16526 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016527 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516528 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1716529
16530 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0116531 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716532 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16533}
16534
[email protected]85f97342013-04-17 06:12:2416535// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
16536// error) in SPDY session, removes the socket from pool and closes the SPDY
16537// session. Verify that new url's from the same HttpNetworkSession (and a new
16538// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0116539TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2316540 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2416541
16542 MockRead reads1[] = {
16543 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
16544 };
16545
Ryan Sleevib8d7ea02018-05-07 20:01:0116546 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2416547
Ryan Hamilton0239aac2018-05-19 00:03:1316548 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916549 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2416550 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116551 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2416552 };
16553
Raul Tambre94493c652019-03-11 17:18:3516554 spdy::SpdySerializedFrame resp2(
16555 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316556 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2416557 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4116558 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
16559 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2416560 };
16561
Ryan Sleevib8d7ea02018-05-07 20:01:0116562 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2416563
[email protected]85f97342013-04-17 06:12:2416564 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616565 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016566 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16567 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2416568
16569 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616570 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016571 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16572 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2416573
danakj1fd259a02016-04-16 03:17:0916574 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5016575 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2416576
16577 // Start the first transaction to set up the SpdySession and verify that
16578 // connection was closed.
16579 HttpRequestInfo request1;
16580 request1.method = "GET";
16581 request1.url = GURL(https_url);
16582 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016583 request1.traffic_annotation =
16584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016585 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416586 TestCompletionCallback callback1;
16587 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016588 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0116589 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2416590
16591 // Now, start the second request and make sure it succeeds.
16592 HttpRequestInfo request2;
16593 request2.method = "GET";
16594 request2.url = GURL(https_url);
16595 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016596 request2.traffic_annotation =
16597 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016598 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416599 TestCompletionCallback callback2;
16600 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016601 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2416602
robpercival214763f2016-07-01 23:27:0116603 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2416604 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16605}
16606
bncd16676a2016-07-20 16:23:0116607TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0316608 ClientSocketPoolManager::set_max_sockets_per_group(
16609 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16610 ClientSocketPoolManager::set_max_sockets_per_pool(
16611 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16612
16613 // Use two different hosts with different IPs so they don't get pooled.
16614 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
16615 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0916616 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0316617
16618 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616619 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316620 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616621 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316622 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16623 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16624
Ryan Hamilton0239aac2018-05-19 00:03:1316625 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916626 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316627 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116628 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0316629 };
Ryan Hamilton0239aac2018-05-19 00:03:1316630 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516631 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316632 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116633 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316634 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116635 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916636 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316637 };
16638
rdsmithebb50aa2015-11-12 03:44:3816639 // Use a separate test instance for the separate SpdySession that will be
16640 // created.
bncd16676a2016-07-20 16:23:0116641 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0116642 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1216643 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0316644
Ryan Hamilton0239aac2018-05-19 00:03:1316645 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4916646 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316647 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116648 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0316649 };
Ryan Hamilton0239aac2018-05-19 00:03:1316650 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516651 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316652 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116653 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316654 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116655 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916656 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316657 };
16658
Ryan Sleevib8d7ea02018-05-07 20:01:0116659 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1216660 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0316661
16662 MockWrite http_write[] = {
16663 MockWrite("GET / HTTP/1.1\r\n"
16664 "Host: www.a.com\r\n"
16665 "Connection: keep-alive\r\n\r\n"),
16666 };
16667
16668 MockRead http_read[] = {
16669 MockRead("HTTP/1.1 200 OK\r\n"),
16670 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16671 MockRead("Content-Length: 6\r\n\r\n"),
16672 MockRead("hello!"),
16673 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116674 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0316675 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16676
16677 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116678 SpdySessionKey spdy_session_key_a(
16679 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16680 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316681 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616682 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316683
16684 TestCompletionCallback callback;
16685 HttpRequestInfo request1;
16686 request1.method = "GET";
16687 request1.url = GURL("https://www.a.com/");
16688 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016689 request1.traffic_annotation =
16690 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816691 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1916692 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316693
tfarina42834112016-09-22 13:38:2016694 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116695 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16696 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316697
16698 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216699 ASSERT_TRUE(response);
16700 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216701 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316702 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216703 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0316704
16705 std::string response_data;
robpercival214763f2016-07-01 23:27:0116706 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316707 EXPECT_EQ("hello!", response_data);
16708 trans.reset();
16709 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616710 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316711
16712 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116713 SpdySessionKey spdy_session_key_b(
16714 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16715 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316716 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616717 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316718 HttpRequestInfo request2;
16719 request2.method = "GET";
16720 request2.url = GURL("https://www.b.com/");
16721 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016722 request2.traffic_annotation =
16723 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816724 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916725 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316726
tfarina42834112016-09-22 13:38:2016727 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116728 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16729 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316730
16731 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216732 ASSERT_TRUE(response);
16733 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216734 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316735 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216736 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116737 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316738 EXPECT_EQ("hello!", response_data);
16739 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616740 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316741 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616742 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316743
16744 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1116745 SpdySessionKey spdy_session_key_a1(
16746 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16747 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316748 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616749 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0316750 HttpRequestInfo request3;
16751 request3.method = "GET";
16752 request3.url = GURL("http://www.a.com/");
16753 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016754 request3.traffic_annotation =
16755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816756 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916757 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316758
tfarina42834112016-09-22 13:38:2016759 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116760 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16761 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316762
16763 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216764 ASSERT_TRUE(response);
16765 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0316766 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16767 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216768 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116769 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316770 EXPECT_EQ("hello!", response_data);
16771 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616772 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316773 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616774 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316775}
16776
bncd16676a2016-07-20 16:23:0116777TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0416778 HttpRequestInfo request;
16779 request.method = "GET";
bncce36dca22015-04-21 22:11:2316780 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016781 request.traffic_annotation =
16782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416783
danakj1fd259a02016-04-16 03:17:0916784 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616785 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416786
ttuttled9dbc652015-09-29 20:00:5916787 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0416788 StaticSocketDataProvider data;
16789 data.set_connect_data(mock_connect);
16790 session_deps_.socket_factory->AddSocketDataProvider(&data);
16791
16792 TestCompletionCallback callback;
16793
tfarina42834112016-09-22 13:38:2016794 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116795 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416796
16797 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116798 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0416799
[email protected]79e1fd62013-06-20 06:50:0416800 // We don't care whether this succeeds or fails, but it shouldn't crash.
16801 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616802 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4716803
16804 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1616805 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4716806 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0116807 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5916808
16809 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1616810 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5916811 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0416812}
16813
bncd16676a2016-07-20 16:23:0116814TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0416815 HttpRequestInfo request;
16816 request.method = "GET";
bncce36dca22015-04-21 22:11:2316817 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016818 request.traffic_annotation =
16819 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416820
danakj1fd259a02016-04-16 03:17:0916821 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616822 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416823
ttuttled9dbc652015-09-29 20:00:5916824 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0416825 StaticSocketDataProvider data;
16826 data.set_connect_data(mock_connect);
16827 session_deps_.socket_factory->AddSocketDataProvider(&data);
16828
16829 TestCompletionCallback callback;
16830
tfarina42834112016-09-22 13:38:2016831 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116832 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416833
16834 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116835 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0416836
[email protected]79e1fd62013-06-20 06:50:0416837 // We don't care whether this succeeds or fails, but it shouldn't crash.
16838 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616839 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4716840
16841 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1616842 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4716843 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0116844 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5916845
16846 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1616847 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5916848 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0416849}
16850
bncd16676a2016-07-20 16:23:0116851TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0416852 HttpRequestInfo request;
16853 request.method = "GET";
bncce36dca22015-04-21 22:11:2316854 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016855 request.traffic_annotation =
16856 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416857
danakj1fd259a02016-04-16 03:17:0916858 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616859 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416860
16861 MockWrite data_writes[] = {
16862 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
16863 };
16864 MockRead data_reads[] = {
16865 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
16866 };
16867
Ryan Sleevib8d7ea02018-05-07 20:01:0116868 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0416869 session_deps_.socket_factory->AddSocketDataProvider(&data);
16870
16871 TestCompletionCallback callback;
16872
tfarina42834112016-09-22 13:38:2016873 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116874 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416875
16876 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116877 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0416878
[email protected]79e1fd62013-06-20 06:50:0416879 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616880 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0416881 EXPECT_TRUE(request_headers.HasHeader("Host"));
16882}
16883
bncd16676a2016-07-20 16:23:0116884TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0416885 HttpRequestInfo request;
16886 request.method = "GET";
bncce36dca22015-04-21 22:11:2316887 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016888 request.traffic_annotation =
16889 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416890
danakj1fd259a02016-04-16 03:17:0916891 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616892 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416893
16894 MockWrite data_writes[] = {
16895 MockWrite(ASYNC, ERR_CONNECTION_RESET),
16896 };
16897 MockRead data_reads[] = {
16898 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
16899 };
16900
Ryan Sleevib8d7ea02018-05-07 20:01:0116901 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0416902 session_deps_.socket_factory->AddSocketDataProvider(&data);
16903
16904 TestCompletionCallback callback;
16905
tfarina42834112016-09-22 13:38:2016906 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116907 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416908
16909 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116910 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0416911
[email protected]79e1fd62013-06-20 06:50:0416912 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616913 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0416914 EXPECT_TRUE(request_headers.HasHeader("Host"));
16915}
16916
bncd16676a2016-07-20 16:23:0116917TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0416918 HttpRequestInfo request;
16919 request.method = "GET";
bncce36dca22015-04-21 22:11:2316920 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016921 request.traffic_annotation =
16922 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416923
danakj1fd259a02016-04-16 03:17:0916924 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616925 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416926
16927 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2316928 MockWrite(
16929 "GET / HTTP/1.1\r\n"
16930 "Host: www.example.org\r\n"
16931 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0416932 };
16933 MockRead data_reads[] = {
16934 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
16935 };
16936
Ryan Sleevib8d7ea02018-05-07 20:01:0116937 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0416938 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_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0416947
[email protected]79e1fd62013-06-20 06:50:0416948 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616949 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0416950 EXPECT_TRUE(request_headers.HasHeader("Host"));
16951}
16952
bncd16676a2016-07-20 16:23:0116953TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0416954 HttpRequestInfo request;
16955 request.method = "GET";
bncce36dca22015-04-21 22:11:2316956 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016957 request.traffic_annotation =
16958 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416959
danakj1fd259a02016-04-16 03:17:0916960 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616961 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416962
16963 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2316964 MockWrite(
16965 "GET / HTTP/1.1\r\n"
16966 "Host: www.example.org\r\n"
16967 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0416968 };
16969 MockRead data_reads[] = {
16970 MockRead(ASYNC, ERR_CONNECTION_RESET),
16971 };
16972
Ryan Sleevib8d7ea02018-05-07 20:01:0116973 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0416974 session_deps_.socket_factory->AddSocketDataProvider(&data);
16975
16976 TestCompletionCallback callback;
16977
tfarina42834112016-09-22 13:38:2016978 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116979 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416980
16981 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116982 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0416983
[email protected]79e1fd62013-06-20 06:50:0416984 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616985 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0416986 EXPECT_TRUE(request_headers.HasHeader("Host"));
16987}
16988
bncd16676a2016-07-20 16:23:0116989TEST_F(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
[email protected]79e1fd62013-06-20 06:50:0416990 HttpRequestInfo request;
16991 request.method = "GET";
bncce36dca22015-04-21 22:11:2316992 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0416993 request.extra_headers.SetHeader("X-Foo", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1016994 request.traffic_annotation =
16995 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416996
danakj1fd259a02016-04-16 03:17:0916997 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616998 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416999
17000 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317001 MockWrite(
17002 "GET / HTTP/1.1\r\n"
17003 "Host: www.example.org\r\n"
17004 "Connection: keep-alive\r\n"
17005 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417006 };
17007 MockRead data_reads[] = {
17008 MockRead("HTTP/1.1 200 OK\r\n"
17009 "Content-Length: 5\r\n\r\n"
17010 "hello"),
17011 MockRead(ASYNC, ERR_UNEXPECTED),
17012 };
17013
Ryan Sleevib8d7ea02018-05-07 20:01:0117014 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417015 session_deps_.socket_factory->AddSocketDataProvider(&data);
17016
17017 TestCompletionCallback callback;
17018
tfarina42834112016-09-22 13:38:2017019 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117020 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417021
17022 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117023 EXPECT_THAT(rv, IsOk());
[email protected]79e1fd62013-06-20 06:50:0417024
17025 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617026 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417027 std::string foo;
17028 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
17029 EXPECT_EQ("bar", foo);
17030}
17031
[email protected]043b68c82013-08-22 23:41:5217032// Tests that when a used socket is returned to the SSL socket pool, it's closed
17033// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117034TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5217035 ClientSocketPoolManager::set_max_sockets_per_group(
17036 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17037 ClientSocketPoolManager::set_max_sockets_per_pool(
17038 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17039
17040 // Set up SSL request.
17041
17042 HttpRequestInfo ssl_request;
17043 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2317044 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017045 ssl_request.traffic_annotation =
17046 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217047
17048 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2317049 MockWrite(
17050 "GET / HTTP/1.1\r\n"
17051 "Host: www.example.org\r\n"
17052 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217053 };
17054 MockRead ssl_reads[] = {
17055 MockRead("HTTP/1.1 200 OK\r\n"),
17056 MockRead("Content-Length: 11\r\n\r\n"),
17057 MockRead("hello world"),
17058 MockRead(SYNCHRONOUS, OK),
17059 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117060 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5217061 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17062
17063 SSLSocketDataProvider ssl(ASYNC, OK);
17064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17065
17066 // Set up HTTP request.
17067
17068 HttpRequestInfo http_request;
17069 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317070 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017071 http_request.traffic_annotation =
17072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217073
17074 MockWrite http_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]043b68c82013-08-22 23:41:5217079 };
17080 MockRead http_reads[] = {
17081 MockRead("HTTP/1.1 200 OK\r\n"),
17082 MockRead("Content-Length: 7\r\n\r\n"),
17083 MockRead("falafel"),
17084 MockRead(SYNCHRONOUS, OK),
17085 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117086 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217087 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17088
danakj1fd259a02016-04-16 03:17:0917089 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217090
17091 // Start the SSL request.
17092 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1617093 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017094 ASSERT_EQ(ERR_IO_PENDING,
17095 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
17096 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5217097
17098 // Start the HTTP request. Pool should stall.
17099 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617100 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017101 ASSERT_EQ(ERR_IO_PENDING,
17102 http_trans.Start(&http_request, http_callback.callback(),
17103 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117104 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217105
17106 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0117107 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217108 std::string response_data;
bnc691fda62016-08-12 00:43:1617109 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217110 EXPECT_EQ("hello world", response_data);
17111
17112 // The SSL socket should automatically be closed, so the HTTP request can
17113 // start.
Matt Menke9d5e2c92019-02-05 01:42:2317114 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4117115 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217116
17117 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0117118 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1617119 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217120 EXPECT_EQ("falafel", response_data);
17121
dcheng48459ac22014-08-26 00:46:4117122 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217123}
17124
17125// Tests that when a SSL connection is established but there's no corresponding
17126// request that needs it, the new socket is closed if the transport socket pool
17127// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117128TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5217129 ClientSocketPoolManager::set_max_sockets_per_group(
17130 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17131 ClientSocketPoolManager::set_max_sockets_per_pool(
17132 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17133
17134 // Set up an ssl request.
17135
17136 HttpRequestInfo ssl_request;
17137 ssl_request.method = "GET";
17138 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1017139 ssl_request.traffic_annotation =
17140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217141
17142 // No data will be sent on the SSL socket.
17143 StaticSocketDataProvider ssl_data;
17144 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17145
17146 SSLSocketDataProvider ssl(ASYNC, OK);
17147 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17148
17149 // Set up HTTP request.
17150
17151 HttpRequestInfo http_request;
17152 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317153 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017154 http_request.traffic_annotation =
17155 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217156
17157 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317158 MockWrite(
17159 "GET / HTTP/1.1\r\n"
17160 "Host: www.example.org\r\n"
17161 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217162 };
17163 MockRead http_reads[] = {
17164 MockRead("HTTP/1.1 200 OK\r\n"),
17165 MockRead("Content-Length: 7\r\n\r\n"),
17166 MockRead("falafel"),
17167 MockRead(SYNCHRONOUS, OK),
17168 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117169 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217170 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17171
danakj1fd259a02016-04-16 03:17:0917172 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217173
17174 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
17175 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2917176 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5917177 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2317178 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217179
17180 // Start the HTTP request. Pool should stall.
17181 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617182 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017183 ASSERT_EQ(ERR_IO_PENDING,
17184 http_trans.Start(&http_request, http_callback.callback(),
17185 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117186 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217187
17188 // The SSL connection will automatically be closed once the connection is
17189 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0117190 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217191 std::string response_data;
bnc691fda62016-08-12 00:43:1617192 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217193 EXPECT_EQ("falafel", response_data);
17194
dcheng48459ac22014-08-26 00:46:4117195 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217196}
17197
bncd16676a2016-07-20 16:23:0117198TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917199 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217200 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917201 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217202 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417203
17204 HttpRequestInfo request;
17205 request.method = "POST";
17206 request.url = GURL("http://www.foo.com/");
17207 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017208 request.traffic_annotation =
17209 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417210
danakj1fd259a02016-04-16 03:17:0917211 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617212 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417213 // Send headers successfully, but get an error while sending the body.
17214 MockWrite data_writes[] = {
17215 MockWrite("POST / HTTP/1.1\r\n"
17216 "Host: www.foo.com\r\n"
17217 "Connection: keep-alive\r\n"
17218 "Content-Length: 3\r\n\r\n"),
17219 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17220 };
17221
17222 MockRead data_reads[] = {
17223 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17224 MockRead("hello world"),
17225 MockRead(SYNCHRONOUS, OK),
17226 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117227 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417228 session_deps_.socket_factory->AddSocketDataProvider(&data);
17229
17230 TestCompletionCallback callback;
17231
tfarina42834112016-09-22 13:38:2017232 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117233 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417234
17235 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117236 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417237
bnc691fda62016-08-12 00:43:1617238 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217239 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417240
wezca1070932016-05-26 20:30:5217241 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417242 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17243
17244 std::string response_data;
bnc691fda62016-08-12 00:43:1617245 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117246 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417247 EXPECT_EQ("hello world", response_data);
17248}
17249
17250// This test makes sure the retry logic doesn't trigger when reading an error
17251// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0117252TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417253 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0917254 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5417255 MockWrite data_writes[] = {
17256 MockWrite("GET / HTTP/1.1\r\n"
17257 "Host: www.foo.com\r\n"
17258 "Connection: keep-alive\r\n\r\n"),
17259 MockWrite("POST / HTTP/1.1\r\n"
17260 "Host: www.foo.com\r\n"
17261 "Connection: keep-alive\r\n"
17262 "Content-Length: 3\r\n\r\n"),
17263 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17264 };
17265
17266 MockRead data_reads[] = {
17267 MockRead("HTTP/1.1 200 Peachy\r\n"
17268 "Content-Length: 14\r\n\r\n"),
17269 MockRead("first response"),
17270 MockRead("HTTP/1.1 400 Not OK\r\n"
17271 "Content-Length: 15\r\n\r\n"),
17272 MockRead("second response"),
17273 MockRead(SYNCHRONOUS, OK),
17274 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117275 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417276 session_deps_.socket_factory->AddSocketDataProvider(&data);
17277
17278 TestCompletionCallback callback;
17279 HttpRequestInfo request1;
17280 request1.method = "GET";
17281 request1.url = GURL("http://www.foo.com/");
17282 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017283 request1.traffic_annotation =
17284 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417285
bnc87dcefc2017-05-25 12:47:5817286 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1917287 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017288 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117289 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417290
17291 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117292 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417293
17294 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5217295 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5417296
wezca1070932016-05-26 20:30:5217297 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5417298 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
17299
17300 std::string response_data1;
17301 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0117302 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417303 EXPECT_EQ("first response", response_data1);
17304 // Delete the transaction to release the socket back into the socket pool.
17305 trans1.reset();
17306
danakj1fd259a02016-04-16 03:17:0917307 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217308 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917309 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217310 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417311
17312 HttpRequestInfo request2;
17313 request2.method = "POST";
17314 request2.url = GURL("http://www.foo.com/");
17315 request2.upload_data_stream = &upload_data_stream;
17316 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017317 request2.traffic_annotation =
17318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417319
bnc691fda62016-08-12 00:43:1617320 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017321 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117322 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417323
17324 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117325 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417326
bnc691fda62016-08-12 00:43:1617327 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217328 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5417329
wezca1070932016-05-26 20:30:5217330 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5417331 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
17332
17333 std::string response_data2;
bnc691fda62016-08-12 00:43:1617334 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0117335 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417336 EXPECT_EQ("second response", response_data2);
17337}
17338
bncd16676a2016-07-20 16:23:0117339TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417340 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0917341 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217342 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917343 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217344 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417345
17346 HttpRequestInfo request;
17347 request.method = "POST";
17348 request.url = GURL("http://www.foo.com/");
17349 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017350 request.traffic_annotation =
17351 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417352
danakj1fd259a02016-04-16 03:17:0917353 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617354 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417355 // Send headers successfully, but get an error while sending the body.
17356 MockWrite data_writes[] = {
17357 MockWrite("POST / HTTP/1.1\r\n"
17358 "Host: www.foo.com\r\n"
17359 "Connection: keep-alive\r\n"
17360 "Content-Length: 3\r\n\r\n"
17361 "fo"),
17362 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17363 };
17364
17365 MockRead data_reads[] = {
17366 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17367 MockRead("hello world"),
17368 MockRead(SYNCHRONOUS, OK),
17369 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117370 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417371 session_deps_.socket_factory->AddSocketDataProvider(&data);
17372
17373 TestCompletionCallback callback;
17374
tfarina42834112016-09-22 13:38:2017375 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117376 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417377
17378 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117379 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417380
bnc691fda62016-08-12 00:43:1617381 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217382 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417383
wezca1070932016-05-26 20:30:5217384 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417385 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17386
17387 std::string response_data;
bnc691fda62016-08-12 00:43:1617388 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117389 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417390 EXPECT_EQ("hello world", response_data);
17391}
17392
17393// This tests the more common case than the previous test, where headers and
17394// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0117395TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0717396 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5417397
17398 HttpRequestInfo request;
17399 request.method = "POST";
17400 request.url = GURL("http://www.foo.com/");
17401 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017402 request.traffic_annotation =
17403 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417404
danakj1fd259a02016-04-16 03:17:0917405 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617406 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417407 // Send headers successfully, but get an error while sending the body.
17408 MockWrite data_writes[] = {
17409 MockWrite("POST / HTTP/1.1\r\n"
17410 "Host: www.foo.com\r\n"
17411 "Connection: keep-alive\r\n"
17412 "Transfer-Encoding: chunked\r\n\r\n"),
17413 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17414 };
17415
17416 MockRead data_reads[] = {
17417 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17418 MockRead("hello world"),
17419 MockRead(SYNCHRONOUS, OK),
17420 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117421 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417422 session_deps_.socket_factory->AddSocketDataProvider(&data);
17423
17424 TestCompletionCallback callback;
17425
tfarina42834112016-09-22 13:38:2017426 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117427 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417428 // Make sure the headers are sent before adding a chunk. This ensures that
17429 // they can't be merged with the body in a single send. Not currently
17430 // necessary since a chunked body is never merged with headers, but this makes
17431 // the test more future proof.
17432 base::RunLoop().RunUntilIdle();
17433
mmenkecbc2b712014-10-09 20:29:0717434 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5417435
17436 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117437 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417438
bnc691fda62016-08-12 00:43:1617439 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217440 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417441
wezca1070932016-05-26 20:30:5217442 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417443 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17444
17445 std::string response_data;
bnc691fda62016-08-12 00:43:1617446 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117447 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417448 EXPECT_EQ("hello world", response_data);
17449}
17450
bncd16676a2016-07-20 16:23:0117451TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
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 Halavatib5e433e62018-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
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 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17473 };
17474
17475 MockRead data_reads[] = {
17476 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
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
bncd16676a2016-07-20 16:23:0117504TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917505 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217506 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917507 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217508 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417509
17510 HttpRequestInfo request;
17511 request.method = "POST";
17512 request.url = GURL("http://www.foo.com/");
17513 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017514 request.traffic_annotation =
17515 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417516
danakj1fd259a02016-04-16 03:17:0917517 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617518 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417519 // Send headers successfully, but get an error while sending the body.
17520 MockWrite data_writes[] = {
17521 MockWrite("POST / HTTP/1.1\r\n"
17522 "Host: www.foo.com\r\n"
17523 "Connection: keep-alive\r\n"
17524 "Content-Length: 3\r\n\r\n"),
17525 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17526 };
17527
17528 MockRead data_reads[] = {
17529 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
17530 MockRead("hello world"),
17531 MockRead(SYNCHRONOUS, OK),
17532 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117533 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417534 session_deps_.socket_factory->AddSocketDataProvider(&data);
17535
17536 TestCompletionCallback callback;
17537
tfarina42834112016-09-22 13:38:2017538 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117539 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417540
17541 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117542 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417543}
17544
bncd16676a2016-07-20 16:23:0117545TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417546 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917547 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217548 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917549 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217550 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417551
17552 HttpRequestInfo request;
17553 request.method = "POST";
17554 request.url = GURL("http://www.foo.com/");
17555 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017556 request.traffic_annotation =
17557 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417558
danakj1fd259a02016-04-16 03:17:0917559 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617560 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417561 // Send headers successfully, but get an error while sending the body.
17562 MockWrite data_writes[] = {
17563 MockWrite("POST / HTTP/1.1\r\n"
17564 "Host: www.foo.com\r\n"
17565 "Connection: keep-alive\r\n"
17566 "Content-Length: 3\r\n\r\n"),
17567 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17568 };
17569
17570 MockRead data_reads[] = {
17571 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17572 MockRead("HTTP/1.0 302 Redirect\r\n"),
17573 MockRead("Location: http://somewhere-else.com/\r\n"),
17574 MockRead("Content-Length: 0\r\n\r\n"),
17575 MockRead(SYNCHRONOUS, OK),
17576 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117577 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417578 session_deps_.socket_factory->AddSocketDataProvider(&data);
17579
17580 TestCompletionCallback callback;
17581
tfarina42834112016-09-22 13:38:2017582 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117583 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417584
17585 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117586 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417587}
17588
bncd16676a2016-07-20 16:23:0117589TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917590 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217591 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917592 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217593 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417594
17595 HttpRequestInfo request;
17596 request.method = "POST";
17597 request.url = GURL("http://www.foo.com/");
17598 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017599 request.traffic_annotation =
17600 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417601
danakj1fd259a02016-04-16 03:17:0917602 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617603 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417604 // Send headers successfully, but get an error while sending the body.
17605 MockWrite data_writes[] = {
17606 MockWrite("POST / HTTP/1.1\r\n"
17607 "Host: www.foo.com\r\n"
17608 "Connection: keep-alive\r\n"
17609 "Content-Length: 3\r\n\r\n"),
17610 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17611 };
17612
17613 MockRead data_reads[] = {
17614 MockRead("HTTP 0.9 rocks!"),
17615 MockRead(SYNCHRONOUS, OK),
17616 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117617 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417618 session_deps_.socket_factory->AddSocketDataProvider(&data);
17619
17620 TestCompletionCallback callback;
17621
tfarina42834112016-09-22 13:38:2017622 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117623 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417624
17625 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117626 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417627}
17628
bncd16676a2016-07-20 16:23:0117629TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0917630 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217631 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917632 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217633 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417634
17635 HttpRequestInfo request;
17636 request.method = "POST";
17637 request.url = GURL("http://www.foo.com/");
17638 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017639 request.traffic_annotation =
17640 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417641
danakj1fd259a02016-04-16 03:17:0917642 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617643 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417644 // Send headers successfully, but get an error while sending the body.
17645 MockWrite data_writes[] = {
17646 MockWrite("POST / HTTP/1.1\r\n"
17647 "Host: www.foo.com\r\n"
17648 "Connection: keep-alive\r\n"
17649 "Content-Length: 3\r\n\r\n"),
17650 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17651 };
17652
17653 MockRead data_reads[] = {
17654 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
17655 MockRead(SYNCHRONOUS, OK),
17656 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117657 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417658 session_deps_.socket_factory->AddSocketDataProvider(&data);
17659
17660 TestCompletionCallback callback;
17661
tfarina42834112016-09-22 13:38:2017662 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117663 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417664
17665 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117666 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417667}
17668
Bence Békydca6bd92018-01-30 13:43:0617669#if BUILDFLAG(ENABLE_WEBSOCKETS)
17670
17671namespace {
17672
17673void AddWebSocketHeaders(HttpRequestHeaders* headers) {
17674 headers->SetHeader("Connection", "Upgrade");
17675 headers->SetHeader("Upgrade", "websocket");
17676 headers->SetHeader("Origin", "http://www.example.org");
17677 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0617678}
17679
17680} // namespace
17681
17682TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0117683 for (bool secure : {true, false}) {
17684 MockWrite data_writes[] = {
17685 MockWrite("GET / HTTP/1.1\r\n"
17686 "Host: www.example.org\r\n"
17687 "Connection: Upgrade\r\n"
17688 "Upgrade: websocket\r\n"
17689 "Origin: http://www.example.org\r\n"
17690 "Sec-WebSocket-Version: 13\r\n"
17691 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17692 "Sec-WebSocket-Extensions: permessage-deflate; "
17693 "client_max_window_bits\r\n\r\n")};
17694
17695 MockRead data_reads[] = {
17696 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17697 "Upgrade: websocket\r\n"
17698 "Connection: Upgrade\r\n"
17699 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
17700
Ryan Sleevib8d7ea02018-05-07 20:01:0117701 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0117702 session_deps_.socket_factory->AddSocketDataProvider(&data);
17703 SSLSocketDataProvider ssl(ASYNC, OK);
17704 if (secure)
17705 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0617706
17707 HttpRequestInfo request;
17708 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0117709 request.url =
17710 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
17711 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1017712 request.traffic_annotation =
17713 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0617714
Bence Béky2fcf4fa2018-04-06 20:06:0117715 TestWebSocketHandshakeStreamCreateHelper
17716 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1517717
Bence Béky2fcf4fa2018-04-06 20:06:0117718 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0617719 HttpNetworkTransaction trans(LOW, session.get());
17720 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0117721 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0617722
17723 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0117724 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
17725 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0617726
Bence Béky2fcf4fa2018-04-06 20:06:0117727 const HttpStreamRequest* stream_request = trans.stream_request_.get();
17728 ASSERT_TRUE(stream_request);
17729 EXPECT_EQ(&websocket_handshake_stream_create_helper,
17730 stream_request->websocket_handshake_stream_create_helper());
17731
17732 rv = callback.WaitForResult();
17733 EXPECT_THAT(rv, IsOk());
17734
17735 EXPECT_TRUE(data.AllReadDataConsumed());
17736 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0617737 }
17738}
17739
Adam Rice425cf122015-01-19 06:18:2417740// Verify that proxy headers are not sent to the destination server when
17741// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0117742TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2417743 HttpRequestInfo request;
17744 request.method = "GET";
bncce36dca22015-04-21 22:11:2317745 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017746 request.traffic_annotation =
17747 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417748 AddWebSocketHeaders(&request.extra_headers);
17749
17750 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5917751 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917752 ProxyResolutionService::CreateFixedFromPacResult(
17753 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417754
danakj1fd259a02016-04-16 03:17:0917755 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2417756
17757 // Since a proxy is configured, try to establish a tunnel.
17758 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1717759 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17760 "Host: www.example.org:443\r\n"
17761 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417762
17763 // After calling trans->RestartWithAuth(), this is the request we should
17764 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1717765 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17766 "Host: www.example.org:443\r\n"
17767 "Proxy-Connection: keep-alive\r\n"
17768 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417769
rsleevidb16bb02015-11-12 23:47:1717770 MockWrite("GET / HTTP/1.1\r\n"
17771 "Host: www.example.org\r\n"
17772 "Connection: Upgrade\r\n"
17773 "Upgrade: websocket\r\n"
17774 "Origin: http://www.example.org\r\n"
17775 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1517776 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17777 "Sec-WebSocket-Extensions: permessage-deflate; "
17778 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417779
17780 // The proxy responds to the connect with a 407, using a persistent
17781 // connection.
17782 MockRead data_reads[] = {
17783 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1517784 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
17785 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
17786 "Content-Length: 0\r\n"
17787 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417788
17789 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
17790
Bence Béky8d1c6052018-02-07 12:48:1517791 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17792 "Upgrade: websocket\r\n"
17793 "Connection: Upgrade\r\n"
17794 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417795
Ryan Sleevib8d7ea02018-05-07 20:01:0117796 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2417797 session_deps_.socket_factory->AddSocketDataProvider(&data);
17798 SSLSocketDataProvider ssl(ASYNC, OK);
17799 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17800
Bence Béky8d1c6052018-02-07 12:48:1517801 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
17802
bnc87dcefc2017-05-25 12:47:5817803 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917804 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2417805 trans->SetWebSocketHandshakeStreamCreateHelper(
17806 &websocket_stream_create_helper);
17807
17808 {
17809 TestCompletionCallback callback;
17810
tfarina42834112016-09-22 13:38:2017811 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117812 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2417813
17814 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117815 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2417816 }
17817
17818 const HttpResponseInfo* response = trans->GetResponseInfo();
17819 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5217820 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2417821 EXPECT_EQ(407, response->headers->response_code());
17822
17823 {
17824 TestCompletionCallback callback;
17825
17826 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
17827 callback.callback());
robpercival214763f2016-07-01 23:27:0117828 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2417829
17830 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117831 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2417832 }
17833
17834 response = trans->GetResponseInfo();
17835 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5217836 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2417837
17838 EXPECT_EQ(101, response->headers->response_code());
17839
17840 trans.reset();
17841 session->CloseAllConnections();
17842}
17843
17844// Verify that proxy headers are not sent to the destination server when
17845// establishing a tunnel for an insecure WebSocket connection.
17846// This requires the authentication info to be injected into the auth cache
17847// due to crbug.com/395064
17848// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0117849TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2417850 HttpRequestInfo request;
17851 request.method = "GET";
bncce36dca22015-04-21 22:11:2317852 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017853 request.traffic_annotation =
17854 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417855 AddWebSocketHeaders(&request.extra_headers);
17856
17857 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5917858 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917859 ProxyResolutionService::CreateFixedFromPacResult(
17860 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417861
danakj1fd259a02016-04-16 03:17:0917862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2417863
17864 MockWrite data_writes[] = {
17865 // Try to establish a tunnel for the WebSocket connection, with
17866 // credentials. Because WebSockets have a separate set of socket pools,
17867 // they cannot and will not use the same TCP/IP connection as the
17868 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1517869 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
17870 "Host: www.example.org:80\r\n"
17871 "Proxy-Connection: keep-alive\r\n"
17872 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417873
Bence Béky8d1c6052018-02-07 12:48:1517874 MockWrite("GET / HTTP/1.1\r\n"
17875 "Host: www.example.org\r\n"
17876 "Connection: Upgrade\r\n"
17877 "Upgrade: websocket\r\n"
17878 "Origin: http://www.example.org\r\n"
17879 "Sec-WebSocket-Version: 13\r\n"
17880 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17881 "Sec-WebSocket-Extensions: permessage-deflate; "
17882 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417883
17884 MockRead data_reads[] = {
17885 // HTTP CONNECT with credentials.
17886 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
17887
17888 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1517889 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17890 "Upgrade: websocket\r\n"
17891 "Connection: Upgrade\r\n"
17892 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417893
Ryan Sleevib8d7ea02018-05-07 20:01:0117894 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2417895 session_deps_.socket_factory->AddSocketDataProvider(&data);
17896
17897 session->http_auth_cache()->Add(
17898 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
17899 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
17900
Bence Béky8d1c6052018-02-07 12:48:1517901 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
17902
bnc87dcefc2017-05-25 12:47:5817903 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917904 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2417905 trans->SetWebSocketHandshakeStreamCreateHelper(
17906 &websocket_stream_create_helper);
17907
17908 TestCompletionCallback callback;
17909
tfarina42834112016-09-22 13:38:2017910 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117911 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2417912
17913 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117914 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2417915
17916 const HttpResponseInfo* response = trans->GetResponseInfo();
17917 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5217918 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2417919
17920 EXPECT_EQ(101, response->headers->response_code());
17921
17922 trans.reset();
17923 session->CloseAllConnections();
17924}
17925
Matt Menke1d6093e32019-03-22 17:33:4317926// WebSockets over QUIC is not supported, including over QUIC proxies.
17927TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
17928 for (bool secure : {true, false}) {
17929 SCOPED_TRACE(secure);
17930 session_deps_.proxy_resolution_service =
17931 ProxyResolutionService::CreateFixedFromPacResult(
17932 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
17933 session_deps_.enable_quic = true;
17934
17935 HttpRequestInfo request;
17936 request.url =
17937 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
17938 AddWebSocketHeaders(&request.extra_headers);
17939 request.traffic_annotation =
17940 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17941
17942 TestWebSocketHandshakeStreamCreateHelper
17943 websocket_handshake_stream_create_helper;
17944
17945 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17946 HttpNetworkTransaction trans(LOW, session.get());
17947 trans.SetWebSocketHandshakeStreamCreateHelper(
17948 &websocket_handshake_stream_create_helper);
17949
17950 TestCompletionCallback callback;
17951 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
17952 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17953
17954 rv = callback.WaitForResult();
17955 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
17956 }
17957}
17958
Bence Békydca6bd92018-01-30 13:43:0617959#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
17960
bncd16676a2016-07-20 16:23:0117961TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0917962 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217963 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917964 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217965 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2217966
17967 HttpRequestInfo request;
17968 request.method = "POST";
17969 request.url = GURL("http://www.foo.com/");
17970 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017971 request.traffic_annotation =
17972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2217973
danakj1fd259a02016-04-16 03:17:0917974 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617975 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2217976 MockWrite data_writes[] = {
17977 MockWrite("POST / HTTP/1.1\r\n"
17978 "Host: www.foo.com\r\n"
17979 "Connection: keep-alive\r\n"
17980 "Content-Length: 3\r\n\r\n"),
17981 MockWrite("foo"),
17982 };
17983
17984 MockRead data_reads[] = {
17985 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
17986 MockRead(SYNCHRONOUS, OK),
17987 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117988 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2217989 session_deps_.socket_factory->AddSocketDataProvider(&data);
17990
17991 TestCompletionCallback callback;
17992
17993 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2017994 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0117995 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2217996
17997 std::string response_data;
bnc691fda62016-08-12 00:43:1617998 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2217999
Ryan Sleevib8d7ea02018-05-07 20:01:0118000 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18001 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218002}
18003
bncd16676a2016-07-20 16:23:0118004TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0918005 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218006 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918007 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218008 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218009
18010 HttpRequestInfo request;
18011 request.method = "POST";
18012 request.url = GURL("http://www.foo.com/");
18013 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018014 request.traffic_annotation =
18015 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218016
danakj1fd259a02016-04-16 03:17:0918017 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618018 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218019 MockWrite data_writes[] = {
18020 MockWrite("POST / HTTP/1.1\r\n"
18021 "Host: www.foo.com\r\n"
18022 "Connection: keep-alive\r\n"
18023 "Content-Length: 3\r\n\r\n"),
18024 MockWrite("foo"),
18025 };
18026
18027 MockRead data_reads[] = {
18028 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
18029 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18030 MockRead(SYNCHRONOUS, OK),
18031 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118032 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218033 session_deps_.socket_factory->AddSocketDataProvider(&data);
18034
18035 TestCompletionCallback callback;
18036
18037 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018038 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118039 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218040
18041 std::string response_data;
bnc691fda62016-08-12 00:43:1618042 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218043
Ryan Sleevib8d7ea02018-05-07 20:01:0118044 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18045 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218046}
18047
bncd16676a2016-07-20 16:23:0118048TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2218049 ChunkedUploadDataStream upload_data_stream(0);
18050
18051 HttpRequestInfo request;
18052 request.method = "POST";
18053 request.url = GURL("http://www.foo.com/");
18054 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018055 request.traffic_annotation =
18056 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218057
danakj1fd259a02016-04-16 03:17:0918058 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618059 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218060 // Send headers successfully, but get an error while sending the body.
18061 MockWrite data_writes[] = {
18062 MockWrite("POST / HTTP/1.1\r\n"
18063 "Host: www.foo.com\r\n"
18064 "Connection: keep-alive\r\n"
18065 "Transfer-Encoding: chunked\r\n\r\n"),
18066 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
18067 };
18068
18069 MockRead data_reads[] = {
18070 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18071 MockRead(SYNCHRONOUS, OK),
18072 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118073 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218074 session_deps_.socket_factory->AddSocketDataProvider(&data);
18075
18076 TestCompletionCallback callback;
18077
18078 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018079 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2218080
18081 base::RunLoop().RunUntilIdle();
18082 upload_data_stream.AppendData("f", 1, false);
18083
18084 base::RunLoop().RunUntilIdle();
18085 upload_data_stream.AppendData("oo", 2, true);
18086
robpercival214763f2016-07-01 23:27:0118087 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218088
18089 std::string response_data;
bnc691fda62016-08-12 00:43:1618090 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218091
Ryan Sleevib8d7ea02018-05-07 20:01:0118092 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18093 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218094}
18095
eustasc7d27da2017-04-06 10:33:2018096void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
18097 const std::string& accept_encoding,
18098 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0318099 const std::string& location,
eustasc7d27da2017-04-06 10:33:2018100 bool should_match) {
18101 HttpRequestInfo request;
18102 request.method = "GET";
18103 request.url = GURL("http://www.foo.com/");
18104 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
18105 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1018106 request.traffic_annotation =
18107 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2018108
18109 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
18110 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18111 // Send headers successfully, but get an error while sending the body.
18112 MockWrite data_writes[] = {
18113 MockWrite("GET / HTTP/1.1\r\n"
18114 "Host: www.foo.com\r\n"
18115 "Connection: keep-alive\r\n"
18116 "Accept-Encoding: "),
18117 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
18118 };
18119
sky50576f32017-05-01 19:28:0318120 std::string response_code = "200 OK";
18121 std::string extra;
18122 if (!location.empty()) {
18123 response_code = "301 Redirect\r\nLocation: ";
18124 response_code.append(location);
18125 }
18126
eustasc7d27da2017-04-06 10:33:2018127 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0318128 MockRead("HTTP/1.0 "),
18129 MockRead(response_code.data()),
18130 MockRead("\r\nContent-Encoding: "),
18131 MockRead(content_encoding.data()),
18132 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2018133 MockRead(SYNCHRONOUS, OK),
18134 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118135 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2018136 session_deps->socket_factory->AddSocketDataProvider(&data);
18137
18138 TestCompletionCallback callback;
18139
18140 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18141 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18142
18143 rv = callback.WaitForResult();
18144 if (should_match) {
18145 EXPECT_THAT(rv, IsOk());
18146 } else {
18147 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
18148 }
18149}
18150
18151TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0318152 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2018153}
18154
18155TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0318156 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
18157 true);
eustasc7d27da2017-04-06 10:33:2018158}
18159
18160TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
18161 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0318162 "", false);
18163}
18164
18165TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
18166 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
18167 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2018168}
18169
xunjieli96f2a402017-06-05 17:24:2718170TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
18171 ProxyConfig proxy_config;
18172 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18173 proxy_config.set_pac_mandatory(true);
18174 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918175 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918176 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18177 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0418178 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2718179
18180 HttpRequestInfo request;
18181 request.method = "GET";
18182 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018183 request.traffic_annotation =
18184 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718185
18186 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18187 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18188
18189 TestCompletionCallback callback;
18190
18191 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18192 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18193 EXPECT_THAT(callback.WaitForResult(),
18194 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18195}
18196
18197TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
18198 ProxyConfig proxy_config;
18199 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18200 proxy_config.set_pac_mandatory(true);
18201 MockAsyncProxyResolverFactory* proxy_resolver_factory =
18202 new MockAsyncProxyResolverFactory(false);
18203 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918204 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918205 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18206 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5918207 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2718208 HttpRequestInfo request;
18209 request.method = "GET";
18210 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018211 request.traffic_annotation =
18212 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718213
18214 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18215 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18216
18217 TestCompletionCallback callback;
18218 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18219 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18220
18221 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
18222 ERR_FAILED, &resolver);
18223 EXPECT_THAT(callback.WaitForResult(),
18224 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18225}
18226
18227TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5918228 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918229 ProxyResolutionService::CreateFixedFromPacResult(
18230 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718231 session_deps_.enable_quic = false;
18232 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18233
18234 HttpRequestInfo request;
18235 request.method = "GET";
18236 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018237 request.traffic_annotation =
18238 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718239
18240 TestCompletionCallback callback;
18241 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18242 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18243 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18244
18245 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
18246}
18247
Douglas Creager3cb042052018-11-06 23:08:5218248//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1418249// Reporting tests
18250
18251#if BUILDFLAG(ENABLE_REPORTING)
18252class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
18253 protected:
18254 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618255 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1418256 auto test_reporting_context = std::make_unique<TestReportingContext>(
18257 &clock_, &tick_clock_, ReportingPolicy());
18258 test_reporting_context_ = test_reporting_context.get();
18259 session_deps_.reporting_service =
18260 ReportingService::CreateForTesting(std::move(test_reporting_context));
18261 }
18262
18263 TestReportingContext* reporting_context() const {
18264 return test_reporting_context_;
18265 }
18266
18267 void clear_reporting_service() {
18268 session_deps_.reporting_service.reset();
18269 test_reporting_context_ = nullptr;
18270 }
18271
18272 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4218273 void RequestPolicy(CertStatus cert_status = 0) {
18274 HttpRequestInfo request;
18275 request.method = "GET";
18276 request.url = GURL(url_);
18277 request.traffic_annotation =
18278 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18279
Lily Chend3930e72019-03-01 19:31:1118280 MockWrite data_writes[] = {
18281 MockWrite("GET / HTTP/1.1\r\n"
18282 "Host: www.example.org\r\n"
18283 "Connection: keep-alive\r\n\r\n"),
18284 };
Douglas Creager134b52e2018-11-09 18:00:1418285 MockRead data_reads[] = {
18286 MockRead("HTTP/1.0 200 OK\r\n"),
18287 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
18288 "\"endpoints\": [{\"url\": "
18289 "\"https://www.example.org/upload/\"}]}\r\n"),
18290 MockRead("\r\n"),
18291 MockRead("hello world"),
18292 MockRead(SYNCHRONOUS, OK),
18293 };
Douglas Creager134b52e2018-11-09 18:00:1418294
Lily Chenfec60d92019-01-24 01:16:4218295 StaticSocketDataProvider reads(data_reads, data_writes);
18296 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1418297
18298 SSLSocketDataProvider ssl(ASYNC, OK);
18299 if (request.url.SchemeIsCryptographic()) {
18300 ssl.ssl_info.cert =
18301 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18302 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218303 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1418304 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18305 }
18306
Douglas Creager134b52e2018-11-09 18:00:1418307 TestCompletionCallback callback;
18308 auto session = CreateSession(&session_deps_);
18309 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18310 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4218311 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1418312 }
18313
18314 protected:
18315 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1418316
18317 private:
18318 TestReportingContext* test_reporting_context_;
18319};
18320
18321TEST_F(HttpNetworkTransactionReportingTest,
18322 DontProcessReportToHeaderNoService) {
18323 base::HistogramTester histograms;
18324 clear_reporting_service();
18325 RequestPolicy();
18326 histograms.ExpectBucketCount(
18327 ReportingHeaderParser::kHeaderOutcomeHistogram,
18328 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
18329}
18330
18331TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
18332 base::HistogramTester histograms;
18333 url_ = "http://www.example.org/";
18334 RequestPolicy();
18335 histograms.ExpectBucketCount(
18336 ReportingHeaderParser::kHeaderOutcomeHistogram,
18337 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18338}
18339
18340TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
18341 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5418342 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
18343 const ReportingClient endpoint =
18344 reporting_context()->cache()->GetEndpointForTesting(
18345 url::Origin::Create(GURL("https://www.example.org/")), "nel",
18346 GURL("https://www.example.org/upload/"));
18347 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1418348}
18349
18350TEST_F(HttpNetworkTransactionReportingTest,
18351 DontProcessReportToHeaderInvalidHttps) {
18352 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218353 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18354 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1418355 histograms.ExpectBucketCount(
18356 ReportingHeaderParser::kHeaderOutcomeHistogram,
18357 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
18358}
18359#endif // BUILDFLAG(ENABLE_REPORTING)
18360
18361//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5218362// Network Error Logging tests
18363
18364#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4218365namespace {
18366
18367const char kUserAgent[] = "Mozilla/1.0";
18368const char kReferrer[] = "https://www.referrer.org/";
18369
18370} // namespace
18371
Douglas Creager3cb042052018-11-06 23:08:5218372class HttpNetworkTransactionNetworkErrorLoggingTest
18373 : public HttpNetworkTransactionTest {
18374 protected:
18375 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618376 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5218377 auto network_error_logging_service =
18378 std::make_unique<TestNetworkErrorLoggingService>();
18379 test_network_error_logging_service_ = network_error_logging_service.get();
18380 session_deps_.network_error_logging_service =
18381 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4218382
18383 extra_headers_.SetHeader("User-Agent", kUserAgent);
18384 extra_headers_.SetHeader("Referer", kReferrer);
18385
18386 request_.method = "GET";
18387 request_.url = GURL(url_);
18388 request_.extra_headers = extra_headers_;
18389 request_.reporting_upload_depth = reporting_upload_depth_;
18390 request_.traffic_annotation =
18391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5218392 }
18393
18394 TestNetworkErrorLoggingService* network_error_logging_service() const {
18395 return test_network_error_logging_service_;
18396 }
18397
18398 void clear_network_error_logging_service() {
18399 session_deps_.network_error_logging_service.reset();
18400 test_network_error_logging_service_ = nullptr;
18401 }
18402
18403 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4218404 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3618405 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318406 MockWrite data_writes[] = {
18407 MockWrite("GET / HTTP/1.1\r\n"
18408 "Host: www.example.org\r\n"
18409 "Connection: keep-alive\r\n"),
18410 MockWrite(ASYNC, extra_header_string.data(),
18411 extra_header_string.size()),
18412 };
Lily Chend3930e72019-03-01 19:31:1118413 MockRead data_reads[] = {
18414 MockRead("HTTP/1.0 200 OK\r\n"),
18415 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18416 MockRead("\r\n"),
18417 MockRead("hello world"),
18418 MockRead(SYNCHRONOUS, OK),
18419 };
Douglas Creager3cb042052018-11-06 23:08:5218420
Lily Chenfec60d92019-01-24 01:16:4218421 StaticSocketDataProvider reads(data_reads, data_writes);
18422 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5218423
18424 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4218425 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5218426 ssl.ssl_info.cert =
18427 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18428 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218429 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5218430 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18431 }
18432
Douglas Creager3cb042052018-11-06 23:08:5218433 TestCompletionCallback callback;
18434 auto session = CreateSession(&session_deps_);
18435 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4218436 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
18437 EXPECT_THAT(callback.GetResult(rv), IsOk());
18438
18439 std::string response_data;
18440 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18441 EXPECT_EQ("hello world", response_data);
18442 }
18443
18444 void CheckReport(size_t index,
18445 int status_code,
18446 int error_type,
18447 IPAddress server_ip = IPAddress::IPv4Localhost()) {
18448 ASSERT_LT(index, network_error_logging_service()->errors().size());
18449
18450 const NetworkErrorLoggingService::RequestDetails& error =
18451 network_error_logging_service()->errors()[index];
18452 EXPECT_EQ(url_, error.uri);
18453 EXPECT_EQ(kReferrer, error.referrer);
18454 EXPECT_EQ(kUserAgent, error.user_agent);
18455 EXPECT_EQ(server_ip, error.server_ip);
18456 EXPECT_EQ("http/1.1", error.protocol);
18457 EXPECT_EQ("GET", error.method);
18458 EXPECT_EQ(status_code, error.status_code);
18459 EXPECT_EQ(error_type, error.type);
18460 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5218461 }
18462
18463 protected:
18464 std::string url_ = "https://www.example.org/";
18465 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4218466 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3618467 HttpRequestHeaders extra_headers_;
18468 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5218469
18470 private:
18471 TestNetworkErrorLoggingService* test_network_error_logging_service_;
18472};
18473
18474TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18475 DontProcessNelHeaderNoService) {
18476 base::HistogramTester histograms;
18477 clear_network_error_logging_service();
18478 RequestPolicy();
18479 histograms.ExpectBucketCount(
18480 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18481 NetworkErrorLoggingService::HeaderOutcome::
18482 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
18483 1);
18484}
18485
18486TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18487 DontProcessNelHeaderHttp) {
18488 base::HistogramTester histograms;
18489 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4218490 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5218491 RequestPolicy();
18492 histograms.ExpectBucketCount(
18493 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18494 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18495}
18496
Lily Chen90ae93cc2019-02-14 01:15:3918497// Don't set NEL policies received on a proxied connection.
18498TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18499 DontProcessNelHeaderProxy) {
18500 session_deps_.proxy_resolution_service =
18501 ProxyResolutionService::CreateFixedFromPacResult(
18502 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
18503 BoundTestNetLog log;
18504 session_deps_.net_log = log.bound().net_log();
18505 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18506
18507 HttpRequestInfo request;
18508 request.method = "GET";
18509 request.url = GURL("https://www.example.org/");
18510 request.traffic_annotation =
18511 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18512
18513 // Since we have proxy, should try to establish tunnel.
18514 MockWrite data_writes1[] = {
18515 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18516 "Host: www.example.org:443\r\n"
18517 "Proxy-Connection: keep-alive\r\n\r\n"),
18518
18519 MockWrite("GET / HTTP/1.1\r\n"
18520 "Host: www.example.org\r\n"
18521 "Connection: keep-alive\r\n\r\n"),
18522 };
18523
18524 MockRead data_reads1[] = {
18525 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18526
18527 MockRead("HTTP/1.1 200 OK\r\n"),
18528 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18529 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18530 MockRead("Content-Length: 100\r\n\r\n"),
18531 MockRead(SYNCHRONOUS, OK),
18532 };
18533
18534 StaticSocketDataProvider data1(data_reads1, data_writes1);
18535 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18536 SSLSocketDataProvider ssl(ASYNC, OK);
18537 ssl.ssl_info.cert =
18538 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18539 ASSERT_TRUE(ssl.ssl_info.cert);
18540 ssl.ssl_info.cert_status = 0;
18541 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18542
18543 TestCompletionCallback callback1;
18544 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18545
18546 int rv = trans.Start(&request, callback1.callback(), log.bound());
18547 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18548
18549 rv = callback1.WaitForResult();
18550 EXPECT_THAT(rv, IsOk());
18551
18552 const HttpResponseInfo* response = trans.GetResponseInfo();
18553 ASSERT_TRUE(response);
18554 EXPECT_EQ(200, response->headers->response_code());
18555 EXPECT_TRUE(response->was_fetched_via_proxy);
18556
18557 // No NEL header was set.
18558 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
18559}
18560
Douglas Creager3cb042052018-11-06 23:08:5218561TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
18562 RequestPolicy();
18563 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
18564 const auto& header = network_error_logging_service()->headers()[0];
18565 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
18566 header.origin);
18567 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
18568 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
18569}
18570
18571TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18572 DontProcessNelHeaderInvalidHttps) {
18573 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218574 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18575 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5218576 histograms.ExpectBucketCount(
18577 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18578 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
18579 1);
18580}
Douglas Creageref5eecdc2018-11-09 20:50:3618581
Lily Chenfec60d92019-01-24 01:16:4218582TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3618583 RequestPolicy();
18584 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4218585 CheckReport(0 /* index */, 200 /* status_code */, OK);
18586}
18587
18588TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18589 CreateReportErrorAfterStart) {
18590 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18591 auto trans =
18592 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18593
18594 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
18595 StaticSocketDataProvider data;
18596 data.set_connect_data(mock_connect);
18597 session_deps_.socket_factory->AddSocketDataProvider(&data);
18598
18599 TestCompletionCallback callback;
18600
18601 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18602 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18603
18604 trans.reset();
18605
18606 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18607 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18608 IPAddress() /* server_ip */);
18609}
18610
18611// Same as above except the error is ASYNC
18612TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18613 CreateReportErrorAfterStartAsync) {
18614 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18615 auto trans =
18616 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18617
18618 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
18619 StaticSocketDataProvider data;
18620 data.set_connect_data(mock_connect);
18621 session_deps_.socket_factory->AddSocketDataProvider(&data);
18622
18623 TestCompletionCallback callback;
18624
18625 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18626 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18627
18628 trans.reset();
18629
18630 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18631 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18632 IPAddress() /* server_ip */);
18633}
18634
18635TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18636 CreateReportReadBodyError) {
18637 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318638 MockWrite data_writes[] = {
18639 MockWrite("GET / HTTP/1.1\r\n"
18640 "Host: www.example.org\r\n"
18641 "Connection: keep-alive\r\n"),
18642 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18643 };
Lily Chend3930e72019-03-01 19:31:1118644 MockRead data_reads[] = {
18645 MockRead("HTTP/1.0 200 OK\r\n"),
18646 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18647 MockRead("hello world"),
18648 MockRead(SYNCHRONOUS, OK),
18649 };
Lily Chenfec60d92019-01-24 01:16:4218650
18651 StaticSocketDataProvider reads(data_reads, data_writes);
18652 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18653
18654 SSLSocketDataProvider ssl(ASYNC, OK);
18655 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18656
18657 // Log start time
18658 base::TimeTicks start_time = base::TimeTicks::Now();
18659
18660 TestCompletionCallback callback;
18661 auto session = CreateSession(&session_deps_);
18662 auto trans =
18663 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18664 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18665 EXPECT_THAT(callback.GetResult(rv), IsOk());
18666
18667 const HttpResponseInfo* response = trans->GetResponseInfo();
18668 ASSERT_TRUE(response);
18669
18670 EXPECT_TRUE(response->headers);
18671 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18672
18673 std::string response_data;
18674 rv = ReadTransaction(trans.get(), &response_data);
18675 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18676
18677 trans.reset();
18678
18679 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18680
18681 CheckReport(0 /* index */, 200 /* status_code */,
18682 ERR_CONTENT_LENGTH_MISMATCH);
18683 const NetworkErrorLoggingService::RequestDetails& error =
18684 network_error_logging_service()->errors()[0];
18685 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18686}
18687
18688// Same as above except the final read is ASYNC.
18689TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18690 CreateReportReadBodyErrorAsync) {
18691 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318692 MockWrite data_writes[] = {
18693 MockWrite("GET / HTTP/1.1\r\n"
18694 "Host: www.example.org\r\n"
18695 "Connection: keep-alive\r\n"),
18696 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18697 };
Lily Chend3930e72019-03-01 19:31:1118698 MockRead data_reads[] = {
18699 MockRead("HTTP/1.0 200 OK\r\n"),
18700 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18701 MockRead("hello world"),
18702 MockRead(ASYNC, OK),
18703 };
Lily Chenfec60d92019-01-24 01:16:4218704
18705 StaticSocketDataProvider reads(data_reads, data_writes);
18706 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18707
18708 SSLSocketDataProvider ssl(ASYNC, OK);
18709 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18710
18711 // Log start time
18712 base::TimeTicks start_time = base::TimeTicks::Now();
18713
18714 TestCompletionCallback callback;
18715 auto session = CreateSession(&session_deps_);
18716 auto trans =
18717 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18718 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18719 EXPECT_THAT(callback.GetResult(rv), IsOk());
18720
18721 const HttpResponseInfo* response = trans->GetResponseInfo();
18722 ASSERT_TRUE(response);
18723
18724 EXPECT_TRUE(response->headers);
18725 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18726
18727 std::string response_data;
18728 rv = ReadTransaction(trans.get(), &response_data);
18729 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18730
18731 trans.reset();
18732
18733 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18734
18735 CheckReport(0 /* index */, 200 /* status_code */,
18736 ERR_CONTENT_LENGTH_MISMATCH);
18737 const NetworkErrorLoggingService::RequestDetails& error =
18738 network_error_logging_service()->errors()[0];
18739 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18740}
18741
18742TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18743 CreateReportRestartWithAuth) {
18744 std::string extra_header_string = extra_headers_.ToString();
18745 static const base::TimeDelta kSleepDuration =
18746 base::TimeDelta::FromMilliseconds(10);
18747
18748 MockWrite data_writes1[] = {
18749 MockWrite("GET / HTTP/1.1\r\n"
18750 "Host: www.example.org\r\n"
18751 "Connection: keep-alive\r\n"),
18752 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18753 };
18754
18755 MockRead data_reads1[] = {
18756 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
18757 // Give a couple authenticate options (only the middle one is actually
18758 // supported).
18759 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
18760 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
18761 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
18762 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18763 // Large content-length -- won't matter, as connection will be reset.
18764 MockRead("Content-Length: 10000\r\n\r\n"),
18765 MockRead(SYNCHRONOUS, ERR_FAILED),
18766 };
18767
18768 // After calling trans->RestartWithAuth(), this is the request we should
18769 // be issuing -- the final header line contains the credentials.
18770 MockWrite data_writes2[] = {
18771 MockWrite("GET / HTTP/1.1\r\n"
18772 "Host: www.example.org\r\n"
18773 "Connection: keep-alive\r\n"
18774 "Authorization: Basic Zm9vOmJhcg==\r\n"),
18775 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18776 };
18777
18778 // Lastly, the server responds with the actual content.
18779 MockRead data_reads2[] = {
18780 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
18781 MockRead("hello world"),
18782 MockRead(SYNCHRONOUS, OK),
18783 };
18784
18785 StaticSocketDataProvider data1(data_reads1, data_writes1);
18786 StaticSocketDataProvider data2(data_reads2, data_writes2);
18787 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18788 session_deps_.socket_factory->AddSocketDataProvider(&data2);
18789
18790 SSLSocketDataProvider ssl1(ASYNC, OK);
18791 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18792 SSLSocketDataProvider ssl2(ASYNC, OK);
18793 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18794
18795 base::TimeTicks start_time = base::TimeTicks::Now();
18796 base::TimeTicks restart_time;
18797
18798 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18799 auto trans =
18800 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18801
18802 TestCompletionCallback callback1;
18803
18804 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
18805 EXPECT_THAT(callback1.GetResult(rv), IsOk());
18806
18807 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18808
18809 TestCompletionCallback callback2;
18810
18811 // Wait 10 ms then restart with auth
18812 FastForwardBy(kSleepDuration);
18813 restart_time = base::TimeTicks::Now();
18814 rv =
18815 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
18816 EXPECT_THAT(callback2.GetResult(rv), IsOk());
18817
18818 std::string response_data;
18819 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
18820 EXPECT_EQ("hello world", response_data);
18821
18822 trans.reset();
18823
18824 // One 401 report for the auth challenge, then a 200 report for the successful
18825 // retry. Note that we don't report the error draining the body, as the first
18826 // request already generated a report for the auth challenge.
18827 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
18828
18829 // Check error report contents
18830 CheckReport(0 /* index */, 401 /* status_code */, OK);
18831 CheckReport(1 /* index */, 200 /* status_code */, OK);
18832
18833 const NetworkErrorLoggingService::RequestDetails& error1 =
18834 network_error_logging_service()->errors()[0];
18835 const NetworkErrorLoggingService::RequestDetails& error2 =
18836 network_error_logging_service()->errors()[1];
18837
18838 // Sanity-check elapsed time values
18839 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
18840 // Check that the start time is refreshed when restarting with auth.
18841 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
18842}
18843
18844// Same as above, except draining the body before restarting fails
18845// asynchronously.
18846TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18847 CreateReportRestartWithAuthAsync) {
18848 std::string extra_header_string = extra_headers_.ToString();
18849 static const base::TimeDelta kSleepDuration =
18850 base::TimeDelta::FromMilliseconds(10);
18851
18852 MockWrite data_writes1[] = {
18853 MockWrite("GET / HTTP/1.1\r\n"
18854 "Host: www.example.org\r\n"
18855 "Connection: keep-alive\r\n"),
18856 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18857 };
18858
18859 MockRead data_reads1[] = {
18860 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
18861 // Give a couple authenticate options (only the middle one is actually
18862 // supported).
18863 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
18864 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
18865 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
18866 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18867 // Large content-length -- won't matter, as connection will be reset.
18868 MockRead("Content-Length: 10000\r\n\r\n"),
18869 MockRead(ASYNC, ERR_FAILED),
18870 };
18871
18872 // After calling trans->RestartWithAuth(), this is the request we should
18873 // be issuing -- the final header line contains the credentials.
18874 MockWrite data_writes2[] = {
18875 MockWrite("GET / HTTP/1.1\r\n"
18876 "Host: www.example.org\r\n"
18877 "Connection: keep-alive\r\n"
18878 "Authorization: Basic Zm9vOmJhcg==\r\n"),
18879 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18880 };
18881
18882 // Lastly, the server responds with the actual content.
18883 MockRead data_reads2[] = {
18884 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
18885 MockRead("hello world"),
18886 MockRead(SYNCHRONOUS, OK),
18887 };
18888
18889 StaticSocketDataProvider data1(data_reads1, data_writes1);
18890 StaticSocketDataProvider data2(data_reads2, data_writes2);
18891 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18892 session_deps_.socket_factory->AddSocketDataProvider(&data2);
18893
18894 SSLSocketDataProvider ssl1(ASYNC, OK);
18895 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18896 SSLSocketDataProvider ssl2(ASYNC, OK);
18897 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18898
18899 base::TimeTicks start_time = base::TimeTicks::Now();
18900 base::TimeTicks restart_time;
18901
18902 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18903 auto trans =
18904 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18905
18906 TestCompletionCallback callback1;
18907
18908 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
18909 EXPECT_THAT(callback1.GetResult(rv), IsOk());
18910
18911 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18912
18913 TestCompletionCallback callback2;
18914
18915 // Wait 10 ms then restart with auth
18916 FastForwardBy(kSleepDuration);
18917 restart_time = base::TimeTicks::Now();
18918 rv =
18919 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
18920 EXPECT_THAT(callback2.GetResult(rv), IsOk());
18921
18922 std::string response_data;
18923 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
18924 EXPECT_EQ("hello world", response_data);
18925
18926 trans.reset();
18927
18928 // One 401 report for the auth challenge, then a 200 report for the successful
18929 // retry. Note that we don't report the error draining the body, as the first
18930 // request already generated a report for the auth challenge.
18931 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
18932
18933 // Check error report contents
18934 CheckReport(0 /* index */, 401 /* status_code */, OK);
18935 CheckReport(1 /* index */, 200 /* status_code */, OK);
18936
18937 const NetworkErrorLoggingService::RequestDetails& error1 =
18938 network_error_logging_service()->errors()[0];
18939 const NetworkErrorLoggingService::RequestDetails& error2 =
18940 network_error_logging_service()->errors()[1];
18941
18942 // Sanity-check elapsed time values
18943 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
18944 // Check that the start time is refreshed when restarting with auth.
18945 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
18946}
18947
18948TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18949 CreateReportRetryKeepAliveConnectionReset) {
18950 std::string extra_header_string = extra_headers_.ToString();
18951 MockWrite data_writes1[] = {
18952 MockWrite("GET / HTTP/1.1\r\n"
18953 "Host: www.example.org\r\n"
18954 "Connection: keep-alive\r\n"),
18955 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18956 MockWrite("GET / HTTP/1.1\r\n"
18957 "Host: www.example.org\r\n"
18958 "Connection: keep-alive\r\n"),
18959 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18960 };
18961
18962 MockRead data_reads1[] = {
18963 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
18964 MockRead("hello"),
18965 // Connection is reset
18966 MockRead(ASYNC, ERR_CONNECTION_RESET),
18967 };
18968
18969 // Successful retry
18970 MockRead data_reads2[] = {
18971 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
18972 MockRead("world"),
18973 MockRead(ASYNC, OK),
18974 };
18975
18976 StaticSocketDataProvider data1(data_reads1, data_writes1);
18977 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
18978 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18979 session_deps_.socket_factory->AddSocketDataProvider(&data2);
18980
18981 SSLSocketDataProvider ssl1(ASYNC, OK);
18982 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18983 SSLSocketDataProvider ssl2(ASYNC, OK);
18984 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18985
18986 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18987 auto trans1 =
18988 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18989
18990 TestCompletionCallback callback1;
18991
18992 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
18993 EXPECT_THAT(callback1.GetResult(rv), IsOk());
18994
18995 std::string response_data;
18996 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
18997 EXPECT_EQ("hello", response_data);
18998
18999 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19000
19001 auto trans2 =
19002 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19003
19004 TestCompletionCallback callback2;
19005
19006 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19007 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19008
19009 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19010 EXPECT_EQ("world", response_data);
19011
19012 trans1.reset();
19013 trans2.reset();
19014
19015 // One OK report from first request, then a ERR_CONNECTION_RESET report from
19016 // the second request, then an OK report from the successful retry.
19017 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19018
19019 // Check error report contents
19020 CheckReport(0 /* index */, 200 /* status_code */, OK);
19021 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
19022 CheckReport(2 /* index */, 200 /* status_code */, OK);
19023}
19024
19025TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19026 CreateReportRetryKeepAlive408) {
19027 std::string extra_header_string = extra_headers_.ToString();
19028 MockWrite data_writes1[] = {
19029 MockWrite("GET / HTTP/1.1\r\n"
19030 "Host: www.example.org\r\n"
19031 "Connection: keep-alive\r\n"),
19032 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19033 MockWrite("GET / HTTP/1.1\r\n"
19034 "Host: www.example.org\r\n"
19035 "Connection: keep-alive\r\n"),
19036 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19037 };
19038
19039 MockRead data_reads1[] = {
19040 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19041 MockRead("hello"),
19042 // 408 Request Timeout
19043 MockRead(SYNCHRONOUS,
19044 "HTTP/1.1 408 Request Timeout\r\n"
19045 "Connection: Keep-Alive\r\n"
19046 "Content-Length: 6\r\n\r\n"
19047 "Pickle"),
19048 };
19049
19050 // Successful retry
19051 MockRead data_reads2[] = {
19052 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19053 MockRead("world"),
19054 MockRead(ASYNC, OK),
19055 };
19056
19057 StaticSocketDataProvider data1(data_reads1, data_writes1);
19058 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19059 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19060 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19061
19062 SSLSocketDataProvider ssl1(ASYNC, OK);
19063 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19064 SSLSocketDataProvider ssl2(ASYNC, OK);
19065 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19066
19067 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19068 auto trans1 =
19069 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19070
19071 TestCompletionCallback callback1;
19072
19073 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19074 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19075
19076 std::string response_data;
19077 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19078 EXPECT_EQ("hello", response_data);
19079
19080 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19081
19082 auto trans2 =
19083 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19084
19085 TestCompletionCallback callback2;
19086
19087 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19088 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19089
19090 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19091 EXPECT_EQ("world", response_data);
19092
19093 trans1.reset();
19094 trans2.reset();
19095
19096 // One 200 report from first request, then a 408 report from
19097 // the second request, then a 200 report from the successful retry.
19098 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19099
19100 // Check error report contents
19101 CheckReport(0 /* index */, 200 /* status_code */, OK);
19102 CheckReport(1 /* index */, 408 /* status_code */, OK);
19103 CheckReport(2 /* index */, 200 /* status_code */, OK);
19104}
19105
19106TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19107 CreateReportRetry421WithoutConnectionPooling) {
19108 // Two hosts resolve to the same IP address.
19109 const std::string ip_addr = "1.2.3.4";
19110 IPAddress ip;
19111 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
19112 IPEndPoint peer_addr = IPEndPoint(ip, 443);
19113
19114 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19115 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
19116 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
19117
19118 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19119
19120 // Two requests on the first connection.
19121 spdy::SpdySerializedFrame req1(
19122 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19123 spdy_util_.UpdateWithStreamDestruction(1);
19124 spdy::SpdySerializedFrame req2(
19125 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
19126 spdy::SpdySerializedFrame rst(
19127 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
19128 MockWrite writes1[] = {
19129 CreateMockWrite(req1, 0),
19130 CreateMockWrite(req2, 3),
19131 CreateMockWrite(rst, 6),
19132 };
19133
19134 // The first one succeeds, the second gets error 421 Misdirected Request.
19135 spdy::SpdySerializedFrame resp1(
19136 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19137 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
19138 spdy::SpdyHeaderBlock response_headers;
19139 response_headers[spdy::kHttp2StatusHeader] = "421";
19140 spdy::SpdySerializedFrame resp2(
19141 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
19142 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
19143 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
19144
19145 MockConnect connect1(ASYNC, OK, peer_addr);
19146 SequencedSocketData data1(connect1, reads1, writes1);
19147 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19148
19149 AddSSLSocketData();
19150
19151 // Retry the second request on a second connection.
19152 SpdyTestUtil spdy_util2;
19153 spdy::SpdySerializedFrame req3(
19154 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
19155 MockWrite writes2[] = {
19156 CreateMockWrite(req3, 0),
19157 };
19158
19159 spdy::SpdySerializedFrame resp3(
19160 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
19161 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
19162 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
19163 MockRead(ASYNC, 0, 3)};
19164
19165 MockConnect connect2(ASYNC, OK, peer_addr);
19166 SequencedSocketData data2(connect2, reads2, writes2);
19167 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19168
19169 AddSSLSocketData();
19170
19171 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3319172 int rv = session_deps_.host_resolver->LoadIntoCache(
19173 HostPortPair("mail.example.com", 443), base::nullopt);
19174 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4219175
19176 HttpRequestInfo request1;
19177 request1.method = "GET";
19178 request1.url = GURL("https://www.example.org/");
19179 request1.load_flags = 0;
19180 request1.traffic_annotation =
19181 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19182 auto trans1 =
19183 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19184
Eric Orthf4db66a2019-02-19 21:35:3319185 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219186 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
19187 EXPECT_THAT(callback.GetResult(rv), IsOk());
19188
19189 const HttpResponseInfo* response = trans1->GetResponseInfo();
19190 ASSERT_TRUE(response);
19191 ASSERT_TRUE(response->headers);
19192 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19193 EXPECT_TRUE(response->was_fetched_via_spdy);
19194 EXPECT_TRUE(response->was_alpn_negotiated);
19195 std::string response_data;
19196 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19197 EXPECT_EQ("hello!", response_data);
19198
19199 trans1.reset();
19200
19201 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19202
19203 HttpRequestInfo request2;
19204 request2.method = "GET";
19205 request2.url = GURL("https://mail.example.org/");
19206 request2.load_flags = 0;
19207 request2.traffic_annotation =
19208 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19209 auto trans2 =
19210 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19211
19212 BoundTestNetLog log;
19213 rv = trans2->Start(&request2, callback.callback(), log.bound());
19214 EXPECT_THAT(callback.GetResult(rv), IsOk());
19215
19216 response = trans2->GetResponseInfo();
19217 ASSERT_TRUE(response);
19218 ASSERT_TRUE(response->headers);
19219 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19220 EXPECT_TRUE(response->was_fetched_via_spdy);
19221 EXPECT_TRUE(response->was_alpn_negotiated);
19222 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19223 EXPECT_EQ("hello!", response_data);
19224
19225 trans2.reset();
19226
19227 // One 200 report from the first request, then a 421 report from the
19228 // second request, then a 200 report from the successful retry.
19229 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19230
19231 // Check error report contents
19232 const NetworkErrorLoggingService::RequestDetails& error1 =
19233 network_error_logging_service()->errors()[0];
19234 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
19235 EXPECT_TRUE(error1.referrer.is_empty());
19236 EXPECT_EQ("", error1.user_agent);
19237 EXPECT_EQ(ip, error1.server_ip);
19238 EXPECT_EQ("h2", error1.protocol);
19239 EXPECT_EQ("GET", error1.method);
19240 EXPECT_EQ(200, error1.status_code);
19241 EXPECT_EQ(OK, error1.type);
19242 EXPECT_EQ(0, error1.reporting_upload_depth);
19243
19244 const NetworkErrorLoggingService::RequestDetails& error2 =
19245 network_error_logging_service()->errors()[1];
19246 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
19247 EXPECT_TRUE(error2.referrer.is_empty());
19248 EXPECT_EQ("", error2.user_agent);
19249 EXPECT_EQ(ip, error2.server_ip);
19250 EXPECT_EQ("h2", error2.protocol);
19251 EXPECT_EQ("GET", error2.method);
19252 EXPECT_EQ(421, error2.status_code);
19253 EXPECT_EQ(OK, error2.type);
19254 EXPECT_EQ(0, error2.reporting_upload_depth);
19255
19256 const NetworkErrorLoggingService::RequestDetails& error3 =
19257 network_error_logging_service()->errors()[2];
19258 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
19259 EXPECT_TRUE(error3.referrer.is_empty());
19260 EXPECT_EQ("", error3.user_agent);
19261 EXPECT_EQ(ip, error3.server_ip);
19262 EXPECT_EQ("h2", error3.protocol);
19263 EXPECT_EQ("GET", error3.method);
19264 EXPECT_EQ(200, error3.status_code);
19265 EXPECT_EQ(OK, error3.type);
19266 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3619267}
19268
Lily Chend3930e72019-03-01 19:31:1119269TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19270 CreateReportCancelAfterStart) {
19271 StaticSocketDataProvider data;
19272 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
19273 session_deps_.socket_factory->AddSocketDataProvider(&data);
19274
19275 TestCompletionCallback callback;
19276 auto session = CreateSession(&session_deps_);
19277 auto trans =
19278 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19279 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19280 EXPECT_EQ(rv, ERR_IO_PENDING);
19281
19282 // Cancel after start.
19283 trans.reset();
19284
19285 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19286 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
19287 IPAddress() /* server_ip */);
19288}
19289
19290TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19291 CreateReportCancelBeforeReadingBody) {
19292 std::string extra_header_string = extra_headers_.ToString();
19293 MockWrite data_writes[] = {
19294 MockWrite("GET / HTTP/1.1\r\n"
19295 "Host: www.example.org\r\n"
19296 "Connection: keep-alive\r\n"),
19297 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19298 };
19299 MockRead data_reads[] = {
19300 MockRead("HTTP/1.0 200 OK\r\n"),
19301 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
19302 };
19303
19304 StaticSocketDataProvider data(data_reads, data_writes);
19305 session_deps_.socket_factory->AddSocketDataProvider(&data);
19306
19307 SSLSocketDataProvider ssl(ASYNC, OK);
19308 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19309
19310 TestCompletionCallback callback;
19311 auto session = CreateSession(&session_deps_);
19312 auto trans =
19313 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19314 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19315 EXPECT_THAT(callback.GetResult(rv), IsOk());
19316
19317 const HttpResponseInfo* response = trans->GetResponseInfo();
19318 ASSERT_TRUE(response);
19319
19320 EXPECT_TRUE(response->headers);
19321 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19322
19323 // Cancel before reading the body.
19324 trans.reset();
19325
19326 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19327 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
19328}
19329
Lily Chen00196ab62018-12-04 19:52:2919330TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
19331 base::HistogramTester histograms;
19332 RequestPolicy();
19333 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19334 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19335
19336 // Make HTTP request
19337 std::string extra_header_string = extra_headers_.ToString();
19338 MockRead data_reads[] = {
19339 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19340 MockRead("hello world"),
19341 MockRead(SYNCHRONOUS, OK),
19342 };
19343 MockWrite data_writes[] = {
19344 MockWrite("GET / HTTP/1.1\r\n"
19345 "Host: www.example.org\r\n"
19346 "Connection: keep-alive\r\n"),
19347 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19348 };
19349
Lily Chend3930e72019-03-01 19:31:1119350 StaticSocketDataProvider data(data_reads, data_writes);
19351 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2919352
Lily Chenfec60d92019-01-24 01:16:4219353 // Insecure url
19354 url_ = "http://www.example.org/";
19355 request_.url = GURL(url_);
19356
Lily Chen00196ab62018-12-04 19:52:2919357 TestCompletionCallback callback;
19358 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4219359 auto trans =
19360 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19361 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19362 EXPECT_THAT(callback.GetResult(rv), IsOk());
19363
19364 std::string response_data;
19365 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19366 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2919367
19368 // Insecure request does not generate a report
19369 histograms.ExpectBucketCount(
19370 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519371 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919372
19373 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19374}
19375
19376TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19377 DontCreateReportHttpError) {
19378 base::HistogramTester histograms;
19379 RequestPolicy();
19380 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19381 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19382
19383 // Make HTTP request that fails
19384 MockRead data_reads[] = {
19385 MockRead("hello world"),
19386 MockRead(SYNCHRONOUS, OK),
19387 };
19388
19389 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19390 session_deps_.socket_factory->AddSocketDataProvider(&data);
19391
Lily Chenfec60d92019-01-24 01:16:4219392 url_ = "http://www.originwithoutpolicy.com:2000/";
19393 request_.url = GURL(url_);
19394
Lily Chen00196ab62018-12-04 19:52:2919395 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19396
Lily Chen00196ab62018-12-04 19:52:2919397 auto trans =
19398 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2919399 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219400 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2919401 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
19402
19403 // Insecure request does not generate a report, regardless of existence of a
19404 // policy for the origin.
19405 histograms.ExpectBucketCount(
19406 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519407 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919408
19409 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19410}
19411
Lily Chen90ae93cc2019-02-14 01:15:3919412// Don't report on proxy auth challenges, don't report if connecting through a
19413// proxy.
19414TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
19415 HttpRequestInfo request;
19416 request.method = "GET";
19417 request.url = GURL("https://www.example.org/");
19418 request.traffic_annotation =
19419 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19420
19421 // Configure against proxy server "myproxy:70".
19422 session_deps_.proxy_resolution_service =
19423 ProxyResolutionService::CreateFixedFromPacResult(
19424 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19425 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19426
19427 // Since we have proxy, should try to establish tunnel.
19428 MockWrite data_writes1[] = {
19429 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19430 "Host: www.example.org:443\r\n"
19431 "Proxy-Connection: keep-alive\r\n\r\n"),
19432 };
19433
19434 // The proxy responds to the connect with a 407, using a non-persistent
19435 // connection.
19436 MockRead data_reads1[] = {
19437 // No credentials.
19438 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
19439 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19440 MockRead("Proxy-Connection: close\r\n\r\n"),
19441 };
19442
19443 MockWrite data_writes2[] = {
19444 // After calling trans->RestartWithAuth(), this is the request we should
19445 // be issuing -- the final header line contains the credentials.
19446 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19447 "Host: www.example.org:443\r\n"
19448 "Proxy-Connection: keep-alive\r\n"
19449 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
19450
19451 MockWrite("GET / HTTP/1.1\r\n"
19452 "Host: www.example.org\r\n"
19453 "Connection: keep-alive\r\n\r\n"),
19454 };
19455
19456 MockRead data_reads2[] = {
19457 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19458
19459 MockRead("HTTP/1.1 200 OK\r\n"),
19460 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19461 MockRead("Content-Length: 5\r\n\r\n"),
19462 MockRead(SYNCHRONOUS, "hello"),
19463 };
19464
19465 StaticSocketDataProvider data1(data_reads1, data_writes1);
19466 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19467 StaticSocketDataProvider data2(data_reads2, data_writes2);
19468 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19469 SSLSocketDataProvider ssl(ASYNC, OK);
19470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19471
19472 TestCompletionCallback callback1;
19473
19474 auto trans =
19475 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19476
19477 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
19478 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19479
19480 const HttpResponseInfo* response = trans->GetResponseInfo();
19481 EXPECT_EQ(407, response->headers->response_code());
19482
19483 std::string response_data;
19484 rv = ReadTransaction(trans.get(), &response_data);
19485 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
19486
19487 // No NEL report is generated for the 407.
19488 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19489
19490 TestCompletionCallback callback2;
19491
19492 rv =
19493 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19494 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19495
19496 response = trans->GetResponseInfo();
19497 EXPECT_EQ(200, response->headers->response_code());
19498
19499 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19500 EXPECT_EQ("hello", response_data);
19501
19502 trans.reset();
19503
19504 // No NEL report is generated because we are behind a proxy.
19505 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19506}
19507
Douglas Creageref5eecdc2018-11-09 20:50:3619508TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19509 ReportContainsUploadDepth) {
19510 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4219511 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3619512 RequestPolicy();
19513 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219514 const NetworkErrorLoggingService::RequestDetails& error =
19515 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3619516 EXPECT_EQ(7, error.reporting_upload_depth);
19517}
19518
Lily Chenfec60d92019-01-24 01:16:4219519TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
19520 std::string extra_header_string = extra_headers_.ToString();
19521 static const base::TimeDelta kSleepDuration =
19522 base::TimeDelta::FromMilliseconds(10);
19523
19524 std::vector<MockWrite> data_writes = {
19525 MockWrite(ASYNC, 0,
19526 "GET / HTTP/1.1\r\n"
19527 "Host: www.example.org\r\n"
19528 "Connection: keep-alive\r\n"),
19529 MockWrite(ASYNC, 1, extra_header_string.data()),
19530 };
19531
19532 std::vector<MockRead> data_reads = {
19533 // Write one byte of the status line, followed by a pause.
19534 MockRead(ASYNC, 2, "H"),
19535 MockRead(ASYNC, ERR_IO_PENDING, 3),
19536 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
19537 MockRead(ASYNC, 5, "hello world"),
19538 MockRead(SYNCHRONOUS, OK, 6),
19539 };
19540
19541 SequencedSocketData data(data_reads, data_writes);
19542 session_deps_.socket_factory->AddSocketDataProvider(&data);
19543
19544 SSLSocketDataProvider ssl(ASYNC, OK);
19545 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19546
19547 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19548
19549 auto trans =
19550 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19551
19552 TestCompletionCallback callback;
19553
19554 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19555 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19556
19557 data.RunUntilPaused();
19558 ASSERT_TRUE(data.IsPaused());
19559 FastForwardBy(kSleepDuration);
19560 data.Resume();
19561
19562 EXPECT_THAT(callback.GetResult(rv), IsOk());
19563
19564 std::string response_data;
19565 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19566 EXPECT_EQ("hello world", response_data);
19567
19568 trans.reset();
19569
Douglas Creageref5eecdc2018-11-09 20:50:3619570 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219571
19572 CheckReport(0 /* index */, 200 /* status_code */, OK);
19573
19574 const NetworkErrorLoggingService::RequestDetails& error =
19575 network_error_logging_service()->errors()[0];
19576
19577 // Sanity-check elapsed time in error report
19578 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3619579}
Lily Chenfec60d92019-01-24 01:16:4219580
Douglas Creager3cb042052018-11-06 23:08:5219581#endif // BUILDFLAG(ENABLE_REPORTING)
19582
Batalov Vladislava4e97a502019-04-11 15:35:2319583TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
19584 HttpRequestInfo request;
19585 request.method = "GET";
19586 request.url = GURL("http://example.org/");
19587
19588 request.load_flags = LOAD_ONLY_FROM_CACHE;
19589
19590 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19591 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19592 TestCompletionCallback callback1;
19593 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
19594
19595 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
19596}
19597
Steven Valdez1c1859172019-04-10 15:33:2819598TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
19599 HttpRequestInfo request;
19600 request.method = "GET";
19601 request.url = GURL("https://www.example.org/");
19602 request.traffic_annotation =
19603 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19604
19605 MockWrite data_writes[] = {
19606 MockWrite("GET / HTTP/1.1\r\n"
19607 "Host: www.example.org\r\n"
19608 "Connection: keep-alive\r\n\r\n"),
19609 };
19610
19611 // The proxy responds to the connect with a 407, using a persistent
19612 // connection.
19613 MockRead data_reads[] = {
19614 MockRead("HTTP/1.1 200 OK\r\n"),
19615 MockRead("Content-Length: 1\r\n\r\n"),
19616 MockRead(SYNCHRONOUS, "1"),
19617 };
19618
19619 StaticSocketDataProvider data(data_reads, data_writes);
19620 session_deps_.socket_factory->AddSocketDataProvider(&data);
19621 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19622 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19623 session_deps_.enable_early_data = true;
19624 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19625
19626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19627
19628 TestCompletionCallback callback;
19629 auto trans =
19630 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19631
19632 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19633 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19634
19635 rv = callback.WaitForResult();
19636 EXPECT_THAT(rv, IsOk());
19637
19638 const HttpResponseInfo* response = trans->GetResponseInfo();
19639 ASSERT_TRUE(response);
19640 ASSERT_TRUE(response->headers);
19641 EXPECT_EQ(200, response->headers->response_code());
19642 EXPECT_EQ(1, response->headers->GetContentLength());
19643
19644 // Check that ConfirmHandshake wasn't called.
19645 ASSERT_FALSE(ssl.ConfirmDataConsumed());
19646 ASSERT_TRUE(ssl.WriteBeforeConfirm());
19647
19648 trans.reset();
19649
19650 session->CloseAllConnections();
19651}
19652
19653TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
19654 HttpRequestInfo request;
19655 request.method = "POST";
19656 request.url = GURL("https://www.example.org/");
19657 request.traffic_annotation =
19658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19659
19660 MockWrite data_writes[] = {
19661 MockWrite(SYNCHRONOUS,
19662 "POST / HTTP/1.1\r\n"
19663 "Host: www.example.org\r\n"
19664 "Connection: keep-alive\r\n"
19665 "Content-Length: 0\r\n\r\n"),
19666 };
19667
19668 // The proxy responds to the connect with a 407, using a persistent
19669 // connection.
19670 MockRead data_reads[] = {
19671 MockRead("HTTP/1.1 200 OK\r\n"),
19672 MockRead("Content-Length: 1\r\n\r\n"),
19673 MockRead(SYNCHRONOUS, "1"),
19674 };
19675
19676 StaticSocketDataProvider data(data_reads, data_writes);
19677 session_deps_.socket_factory->AddSocketDataProvider(&data);
19678 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19679 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19680 session_deps_.enable_early_data = true;
19681 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19682
19683 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19684
19685 TestCompletionCallback callback;
19686 auto trans =
19687 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19688
19689 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19690 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19691
19692 rv = callback.WaitForResult();
19693 EXPECT_THAT(rv, IsOk());
19694
19695 const HttpResponseInfo* response = trans->GetResponseInfo();
19696 ASSERT_TRUE(response);
19697 ASSERT_TRUE(response->headers);
19698 EXPECT_EQ(200, response->headers->response_code());
19699 EXPECT_EQ(1, response->headers->GetContentLength());
19700
19701 // Check that the Write didn't get called before ConfirmHandshake completed.
19702 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19703
19704 trans.reset();
19705
19706 session->CloseAllConnections();
19707}
19708
19709TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
19710 HttpRequestInfo request;
19711 request.method = "POST";
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(ASYNC,
19718 "POST / HTTP/1.1\r\n"
19719 "Host: www.example.org\r\n"
19720 "Connection: keep-alive\r\n"
19721 "Content-Length: 0\r\n\r\n"),
19722 };
19723
19724 // The proxy responds to the connect with a 407, using a persistent
19725 // connection.
19726 MockRead data_reads[] = {
19727 MockRead("HTTP/1.1 200 OK\r\n"),
19728 MockRead("Content-Length: 1\r\n\r\n"),
19729 MockRead(SYNCHRONOUS, "1"),
19730 };
19731
19732 StaticSocketDataProvider data(data_reads, data_writes);
19733 session_deps_.socket_factory->AddSocketDataProvider(&data);
19734 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19735 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19736 session_deps_.enable_early_data = true;
19737 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19738
19739 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19740
19741 TestCompletionCallback callback;
19742 auto trans =
19743 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19744
19745 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19746 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19747
19748 rv = callback.WaitForResult();
19749 EXPECT_THAT(rv, IsOk());
19750
19751 const HttpResponseInfo* response = trans->GetResponseInfo();
19752 ASSERT_TRUE(response);
19753 ASSERT_TRUE(response->headers);
19754 EXPECT_EQ(200, response->headers->response_code());
19755 EXPECT_EQ(1, response->headers->GetContentLength());
19756
19757 // Check that the Write didn't get called before ConfirmHandshake completed.
19758 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19759
19760 trans.reset();
19761
19762 session->CloseAllConnections();
19763}
19764
19765TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
19766 HttpRequestInfo request;
19767 request.method = "POST";
19768 request.url = GURL("https://www.example.org/");
19769 request.traffic_annotation =
19770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19771
19772 MockWrite data_writes[] = {
19773 MockWrite(SYNCHRONOUS,
19774 "POST / HTTP/1.1\r\n"
19775 "Host: www.example.org\r\n"
19776 "Connection: keep-alive\r\n"
19777 "Content-Length: 0\r\n\r\n"),
19778 };
19779
19780 // The proxy responds to the connect with a 407, using a persistent
19781 // connection.
19782 MockRead data_reads[] = {
19783 MockRead("HTTP/1.1 200 OK\r\n"),
19784 MockRead("Content-Length: 1\r\n\r\n"),
19785 MockRead(SYNCHRONOUS, "1"),
19786 };
19787
19788 StaticSocketDataProvider data(data_reads, data_writes);
19789 session_deps_.socket_factory->AddSocketDataProvider(&data);
19790 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19791 ssl.confirm = MockConfirm(ASYNC, OK);
19792 session_deps_.enable_early_data = true;
19793 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19794
19795 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19796
19797 TestCompletionCallback callback;
19798 auto trans =
19799 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19800
19801 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19802 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19803
19804 rv = callback.WaitForResult();
19805 EXPECT_THAT(rv, IsOk());
19806
19807 const HttpResponseInfo* response = trans->GetResponseInfo();
19808 ASSERT_TRUE(response);
19809 ASSERT_TRUE(response->headers);
19810 EXPECT_EQ(200, response->headers->response_code());
19811 EXPECT_EQ(1, response->headers->GetContentLength());
19812
19813 // Check that the Write didn't get called before ConfirmHandshake completed.
19814 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19815
19816 trans.reset();
19817
19818 session->CloseAllConnections();
19819}
19820
19821TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
19822 HttpRequestInfo request;
19823 request.method = "POST";
19824 request.url = GURL("https://www.example.org/");
19825 request.traffic_annotation =
19826 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19827
19828 MockWrite data_writes[] = {
19829 MockWrite(ASYNC,
19830 "POST / HTTP/1.1\r\n"
19831 "Host: www.example.org\r\n"
19832 "Connection: keep-alive\r\n"
19833 "Content-Length: 0\r\n\r\n"),
19834 };
19835
19836 // The proxy responds to the connect with a 407, using a persistent
19837 // connection.
19838 MockRead data_reads[] = {
19839 MockRead("HTTP/1.1 200 OK\r\n"),
19840 MockRead("Content-Length: 1\r\n\r\n"),
19841 MockRead(SYNCHRONOUS, "1"),
19842 };
19843
19844 StaticSocketDataProvider data(data_reads, data_writes);
19845 session_deps_.socket_factory->AddSocketDataProvider(&data);
19846 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19847 ssl.confirm = MockConfirm(ASYNC, OK);
19848 session_deps_.enable_early_data = true;
19849 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19850
19851 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19852
19853 TestCompletionCallback callback;
19854 auto trans =
19855 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19856
19857 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19859
19860 rv = callback.WaitForResult();
19861 EXPECT_THAT(rv, IsOk());
19862
19863 const HttpResponseInfo* response = trans->GetResponseInfo();
19864 ASSERT_TRUE(response);
19865 ASSERT_TRUE(response->headers);
19866 EXPECT_EQ(200, response->headers->response_code());
19867 EXPECT_EQ(1, response->headers->GetContentLength());
19868
19869 // Check that the Write didn't get called before ConfirmHandshake completed.
19870 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19871
19872 trans.reset();
19873
19874 session->CloseAllConnections();
19875}
19876
19877TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
19878 HttpRequestInfo request;
19879 request.method = "POST";
19880 request.url = GURL("https://www.example.org/");
19881 request.traffic_annotation =
19882 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19883
19884 MockWrite data_writes[] = {
19885 MockWrite("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(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
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, IsError(ERR_SSL_PROTOCOL_ERROR));
19917
19918 // Check that the Write didn't get called before ConfirmHandshake completed.
19919 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19920
19921 trans.reset();
19922
19923 session->CloseAllConnections();
19924}
19925
19926TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
19927 HttpRequestInfo request;
19928 request.method = "POST";
19929 request.url = GURL("https://www.example.org/");
19930 request.traffic_annotation =
19931 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19932
19933 MockWrite data_writes[] = {
19934 MockWrite("POST / HTTP/1.1\r\n"
19935 "Host: www.example.org\r\n"
19936 "Connection: keep-alive\r\n"
19937 "Content-Length: 0\r\n\r\n"),
19938 };
19939
19940 // The proxy responds to the connect with a 407, using a persistent
19941 // connection.
19942 MockRead data_reads[] = {
19943 MockRead("HTTP/1.1 200 OK\r\n"),
19944 MockRead("Content-Length: 1\r\n\r\n"),
19945 MockRead(SYNCHRONOUS, "1"),
19946 };
19947
19948 StaticSocketDataProvider data(data_reads, data_writes);
19949 session_deps_.socket_factory->AddSocketDataProvider(&data);
19950 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19951 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
19952 session_deps_.enable_early_data = true;
19953 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19954
19955 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19956
19957 TestCompletionCallback callback;
19958 auto trans =
19959 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19960
19961 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19962 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19963
19964 rv = callback.WaitForResult();
19965 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
19966
19967 // Check that the Write didn't get called before ConfirmHandshake completed.
19968 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19969
19970 trans.reset();
19971
19972 session->CloseAllConnections();
19973}
19974
David Benjamin2eb827f2019-04-29 18:31:0419975// Test the proxy and origin server each requesting both TLS client certificates
19976// and HTTP auth. This is a regression test for https://crbug.com/946406.
19977TEST_F(HttpNetworkTransactionTest, AuthEverything) {
19978 // Note these hosts must match the CheckBasic*Auth() functions.
19979 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
19980 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19981
19982 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
19983 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
19984
19985 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
19986 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
19987 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
19988 ASSERT_TRUE(identity_proxy);
19989
19990 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
19991 cert_request_info_origin->host_and_port =
19992 HostPortPair("www.example.org", 443);
19993
19994 std::unique_ptr<FakeClientCertIdentity> identity_origin =
19995 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
19996 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
19997 ASSERT_TRUE(identity_origin);
19998
19999 HttpRequestInfo request;
20000 request.method = "GET";
20001 request.url = GURL("https://www.example.org/");
20002 request.traffic_annotation =
20003 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20004
20005 // First, the client connects to the proxy, which requests a client
20006 // certificate.
20007 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20008 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20009 ssl_proxy1.expected_send_client_cert = false;
20010 StaticSocketDataProvider data1;
20011 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20013
20014 // The client responds with a certificate on a new connection. The handshake
20015 // succeeds.
20016 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20017 ssl_proxy2.expected_send_client_cert = true;
20018 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
20019 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20020 std::vector<MockWrite> mock_writes2;
20021 std::vector<MockRead> mock_reads2;
20022 mock_writes2.emplace_back(
20023 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20024 "Host: www.example.org:443\r\n"
20025 "Proxy-Connection: keep-alive\r\n\r\n");
20026 mock_reads2.emplace_back(
20027 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20028 "Content-Length: 0\r\n"
20029 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20030 // The client retries with credentials.
20031 mock_writes2.emplace_back(
20032 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20033 "Host: www.example.org:443\r\n"
20034 "Proxy-Connection: keep-alive\r\n"
20035 // Authenticate as proxyuser:proxypass.
20036 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20037 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20038 // The origin requests client certificates.
20039 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20040 ssl_origin2.cert_request_info = cert_request_info_origin.get();
20041 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20042 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20043 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20044 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
20045
20046 // The client responds to the origin client certificate request on a new
20047 // connection.
20048 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20049 ssl_proxy3.expected_send_client_cert = true;
20050 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20051 std::vector<MockWrite> mock_writes3;
20052 std::vector<MockRead> mock_reads3;
20053 mock_writes3.emplace_back(
20054 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20055 "Host: www.example.org:443\r\n"
20056 "Proxy-Connection: keep-alive\r\n"
20057 // Authenticate as proxyuser:proxypass.
20058 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20059 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20060 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
20061 ssl_origin3.expected_send_client_cert = true;
20062 ssl_origin3.expected_client_cert = identity_origin->certificate();
20063 // The client sends the origin HTTP request, which results in another HTTP
20064 // auth request.
20065 mock_writes3.emplace_back(
20066 "GET / HTTP/1.1\r\n"
20067 "Host: www.example.org\r\n"
20068 "Connection: keep-alive\r\n\r\n");
20069 mock_reads3.emplace_back(
20070 "HTTP/1.1 401 Unauthorized\r\n"
20071 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20072 "Content-Length: 0\r\n\r\n");
20073 // The client retries with credentials, and the request finally succeeds.
20074 mock_writes3.emplace_back(
20075 "GET / HTTP/1.1\r\n"
20076 "Host: www.example.org\r\n"
20077 "Connection: keep-alive\r\n"
20078 // Authenticate as user:pass.
20079 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20080 mock_reads3.emplace_back(
20081 "HTTP/1.1 200 OK\r\n"
20082 "Content-Length: 0\r\n\r\n");
20083 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20084 session_deps_.socket_factory->AddSocketDataProvider(&data3);
20085 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20086 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
20087
20088 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20089
20090 // Start the request.
20091 TestCompletionCallback callback;
20092 auto trans =
20093 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20094 int rv = callback.GetResult(
20095 trans->Start(&request, callback.callback(), NetLogWithSource()));
20096
20097 // Handle the proxy client certificate challenge.
20098 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20099 SSLCertRequestInfo* cert_request_info =
20100 trans->GetResponseInfo()->cert_request_info.get();
20101 ASSERT_TRUE(cert_request_info);
20102 EXPECT_TRUE(cert_request_info->is_proxy);
20103 EXPECT_EQ(cert_request_info->host_and_port,
20104 cert_request_info_proxy->host_and_port);
20105 rv = callback.GetResult(trans->RestartWithCertificate(
20106 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20107 callback.callback()));
20108
20109 // Handle the proxy HTTP auth challenge.
20110 ASSERT_THAT(rv, IsOk());
20111 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20112 EXPECT_TRUE(
20113 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20114 rv = callback.GetResult(trans->RestartWithAuth(
20115 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20116 callback.callback()));
20117
20118 // Handle the origin client certificate challenge.
20119 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20120 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20121 ASSERT_TRUE(cert_request_info);
20122 EXPECT_FALSE(cert_request_info->is_proxy);
20123 EXPECT_EQ(cert_request_info->host_and_port,
20124 cert_request_info_origin->host_and_port);
20125 rv = callback.GetResult(trans->RestartWithCertificate(
20126 identity_origin->certificate(), identity_origin->ssl_private_key(),
20127 callback.callback()));
20128
20129 // Handle the origin HTTP auth challenge.
20130 ASSERT_THAT(rv, IsOk());
20131 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20132 EXPECT_TRUE(
20133 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20134 rv = callback.GetResult(trans->RestartWithAuth(
20135 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20136 callback.callback()));
20137
20138 // The request completes.
20139 ASSERT_THAT(rv, IsOk());
20140 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20141}
20142
20143// Test the proxy and origin server each requesting both TLS client certificates
20144// and HTTP auth and each HTTP auth closing the connection. This is a regression
20145// test for https://crbug.com/946406.
20146TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
20147 // Note these hosts must match the CheckBasic*Auth() functions.
20148 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20149 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20150
20151 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20152 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20153
20154 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20155 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20156 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20157 ASSERT_TRUE(identity_proxy);
20158
20159 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20160 cert_request_info_origin->host_and_port =
20161 HostPortPair("www.example.org", 443);
20162
20163 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20164 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20165 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20166 ASSERT_TRUE(identity_origin);
20167
20168 HttpRequestInfo request;
20169 request.method = "GET";
20170 request.url = GURL("https://www.example.org/");
20171 request.traffic_annotation =
20172 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20173
20174 // First, the client connects to the proxy, which requests a client
20175 // certificate.
20176 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20177 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20178 ssl_proxy1.expected_send_client_cert = false;
20179 StaticSocketDataProvider data1;
20180 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20181 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20182
20183 // The client responds with a certificate on a new connection. The handshake
20184 // succeeds.
20185 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20186 ssl_proxy2.expected_send_client_cert = true;
20187 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
20188 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20189 std::vector<MockWrite> mock_writes2;
20190 std::vector<MockRead> mock_reads2;
20191 mock_writes2.emplace_back(
20192 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20193 "Host: www.example.org:443\r\n"
20194 "Proxy-Connection: keep-alive\r\n\r\n");
20195 mock_reads2.emplace_back(
20196 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20197 "Content-Length: 0\r\n"
20198 "Proxy-Connection: close\r\n"
20199 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20200 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20201 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20202 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20203
20204 // The client retries with credentials on a new connection.
20205 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20206 ssl_proxy3.expected_send_client_cert = true;
20207 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20208 std::vector<MockWrite> mock_writes3;
20209 std::vector<MockRead> mock_reads3;
20210 mock_writes3.emplace_back(
20211 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20212 "Host: www.example.org:443\r\n"
20213 "Proxy-Connection: keep-alive\r\n"
20214 // Authenticate as proxyuser:proxypass.
20215 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20216 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20217 // The origin requests client certificates.
20218 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20219 ssl_origin3.cert_request_info = cert_request_info_origin.get();
20220 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20221 session_deps_.socket_factory->AddSocketDataProvider(&data3);
20222 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20223 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
20224
20225 // The client responds to the origin client certificate request on a new
20226 // connection.
20227 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
20228 ssl_proxy4.expected_send_client_cert = true;
20229 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
20230 std::vector<MockWrite> mock_writes4;
20231 std::vector<MockRead> mock_reads4;
20232 mock_writes4.emplace_back(
20233 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20234 "Host: www.example.org:443\r\n"
20235 "Proxy-Connection: keep-alive\r\n"
20236 // Authenticate as proxyuser:proxypass.
20237 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20238 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20239 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
20240 ssl_origin4.expected_send_client_cert = true;
20241 ssl_origin4.expected_client_cert = identity_origin->certificate();
20242 // The client sends the origin HTTP request, which results in another HTTP
20243 // auth request and closed connection.
20244 mock_writes4.emplace_back(
20245 "GET / HTTP/1.1\r\n"
20246 "Host: www.example.org\r\n"
20247 "Connection: keep-alive\r\n\r\n");
20248 mock_reads4.emplace_back(
20249 "HTTP/1.1 401 Unauthorized\r\n"
20250 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20251 "Connection: close\r\n"
20252 "Content-Length: 0\r\n\r\n");
20253 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
20254 session_deps_.socket_factory->AddSocketDataProvider(&data4);
20255 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
20256 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
20257
20258 // The client retries with credentials on a new connection, and the request
20259 // finally succeeds.
20260 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
20261 ssl_proxy5.expected_send_client_cert = true;
20262 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
20263 std::vector<MockWrite> mock_writes5;
20264 std::vector<MockRead> mock_reads5;
20265 mock_writes5.emplace_back(
20266 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20267 "Host: www.example.org:443\r\n"
20268 "Proxy-Connection: keep-alive\r\n"
20269 // Authenticate as proxyuser:proxypass.
20270 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20271 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20272 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
20273 ssl_origin5.expected_send_client_cert = true;
20274 ssl_origin5.expected_client_cert = identity_origin->certificate();
20275 mock_writes5.emplace_back(
20276 "GET / HTTP/1.1\r\n"
20277 "Host: www.example.org\r\n"
20278 "Connection: keep-alive\r\n"
20279 // Authenticate as user:pass.
20280 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20281 mock_reads5.emplace_back(
20282 "HTTP/1.1 200 OK\r\n"
20283 "Connection: close\r\n"
20284 "Content-Length: 0\r\n\r\n");
20285 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
20286 session_deps_.socket_factory->AddSocketDataProvider(&data5);
20287 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
20288 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
20289
20290 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20291
20292 // Start the request.
20293 TestCompletionCallback callback;
20294 auto trans =
20295 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20296 int rv = callback.GetResult(
20297 trans->Start(&request, callback.callback(), NetLogWithSource()));
20298
20299 // Handle the proxy client certificate challenge.
20300 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20301 SSLCertRequestInfo* cert_request_info =
20302 trans->GetResponseInfo()->cert_request_info.get();
20303 ASSERT_TRUE(cert_request_info);
20304 EXPECT_TRUE(cert_request_info->is_proxy);
20305 EXPECT_EQ(cert_request_info->host_and_port,
20306 cert_request_info_proxy->host_and_port);
20307 rv = callback.GetResult(trans->RestartWithCertificate(
20308 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20309 callback.callback()));
20310
20311 // Handle the proxy HTTP auth challenge.
20312 ASSERT_THAT(rv, IsOk());
20313 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20314 EXPECT_TRUE(
20315 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20316 rv = callback.GetResult(trans->RestartWithAuth(
20317 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20318 callback.callback()));
20319
20320 // Handle the origin client certificate challenge.
20321 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20322 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20323 ASSERT_TRUE(cert_request_info);
20324 EXPECT_FALSE(cert_request_info->is_proxy);
20325 EXPECT_EQ(cert_request_info->host_and_port,
20326 cert_request_info_origin->host_and_port);
20327 rv = callback.GetResult(trans->RestartWithCertificate(
20328 identity_origin->certificate(), identity_origin->ssl_private_key(),
20329 callback.callback()));
20330
20331 // Handle the origin HTTP auth challenge.
20332 ASSERT_THAT(rv, IsOk());
20333 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20334 EXPECT_TRUE(
20335 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20336 rv = callback.GetResult(trans->RestartWithAuth(
20337 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20338 callback.callback()));
20339
20340 // The request completes.
20341 ASSERT_THAT(rv, IsOk());
20342 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20343}
20344
20345// Test the proxy requesting HTTP auth and the server requesting TLS client
20346// certificates. This is a regression test for https://crbug.com/946406.
20347TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
20348 // Note these hosts must match the CheckBasic*Auth() functions.
20349 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20350 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20351
20352 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20353 cert_request_info_origin->host_and_port =
20354 HostPortPair("www.example.org", 443);
20355
20356 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20357 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20358 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20359 ASSERT_TRUE(identity_origin);
20360
20361 HttpRequestInfo request;
20362 request.method = "GET";
20363 request.url = GURL("https://www.example.org/");
20364 request.traffic_annotation =
20365 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20366
20367 // The client connects to the proxy. The handshake succeeds.
20368 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
20369 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20370 std::vector<MockWrite> mock_writes1;
20371 std::vector<MockRead> mock_reads1;
20372 mock_writes1.emplace_back(
20373 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20374 "Host: www.example.org:443\r\n"
20375 "Proxy-Connection: keep-alive\r\n\r\n");
20376 mock_reads1.emplace_back(
20377 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20378 "Content-Length: 0\r\n"
20379 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20380 // The client retries with credentials, and the request finally succeeds.
20381 mock_writes1.emplace_back(
20382 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20383 "Host: www.example.org:443\r\n"
20384 "Proxy-Connection: keep-alive\r\n"
20385 // Authenticate as proxyuser:proxypass.
20386 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20387 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20388 // The origin requests client certificates.
20389 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20390 ssl_origin1.cert_request_info = cert_request_info_origin.get();
20391 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
20392 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20393 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20394 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
20395
20396 // The client responds to the origin client certificate request on a new
20397 // connection.
20398 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20399 std::vector<MockWrite> mock_writes2;
20400 std::vector<MockRead> mock_reads2;
20401 mock_writes2.emplace_back(
20402 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20403 "Host: www.example.org:443\r\n"
20404 "Proxy-Connection: keep-alive\r\n"
20405 // Authenticate as proxyuser:proxypass.
20406 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20407 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20408 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
20409 ssl_origin2.expected_send_client_cert = true;
20410 ssl_origin2.expected_client_cert = identity_origin->certificate();
20411 // The client sends the origin HTTP request, which succeeds.
20412 mock_writes2.emplace_back(
20413 "GET / HTTP/1.1\r\n"
20414 "Host: www.example.org\r\n"
20415 "Connection: keep-alive\r\n\r\n");
20416 mock_reads2.emplace_back(
20417 "HTTP/1.1 200 OK\r\n"
20418 "Content-Length: 0\r\n\r\n");
20419 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20420 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20421 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
20423
20424 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20425
20426 // Start the request.
20427 TestCompletionCallback callback;
20428 auto trans =
20429 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20430 int rv = callback.GetResult(
20431 trans->Start(&request, callback.callback(), NetLogWithSource()));
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 SSLCertRequestInfo* cert_request_info =
20445 trans->GetResponseInfo()->cert_request_info.get();
20446 ASSERT_TRUE(cert_request_info);
20447 EXPECT_FALSE(cert_request_info->is_proxy);
20448 EXPECT_EQ(cert_request_info->host_and_port,
20449 cert_request_info_origin->host_and_port);
20450 rv = callback.GetResult(trans->RestartWithCertificate(
20451 identity_origin->certificate(), identity_origin->ssl_private_key(),
20452 callback.callback()));
20453
20454 // The request completes.
20455 ASSERT_THAT(rv, IsOk());
20456 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20457}
20458
[email protected]89ceba9a2009-03-21 03:46:0620459} // namespace net