blob: 3516a20eb05d9bb586b215eb48bfcd6c37254e88 [file] [log] [blame]
[email protected]23e482282013-06-14 16:08:021// Copyright 2013 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]5285d972011-10-18 18:56:348#include <stdarg.h>
sclittlebe1ccf62015-09-02 19:40:369#include <stdint.h>
danakj1fd259a02016-04-16 03:17:0910
avibf0746c2015-12-09 19:53:1411#include <limits>
rdsmith1d343be52016-10-21 20:37:5012#include <set>
[email protected]5285d972011-10-18 18:56:3413#include <string>
dchengc7eeda422015-12-26 03:56:4814#include <utility>
[email protected]95d88ffe2010-02-04 21:25:3315#include <vector>
[email protected]77848d12008-11-14 00:00:2216
Sebastien Marchand6d0558fd2019-01-25 16:49:3717#include "base/bind.h"
[email protected]68bf9152008-09-25 19:47:3018#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5219#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2920#include "base/files/file_util.h"
[email protected]f3da152d2012-06-02 01:00:5721#include "base/json/json_writer.h"
Adam Rice425cf122015-01-19 06:18:2422#include "base/logging.h"
danakj1fd259a02016-04-16 03:17:0923#include "base/memory/ptr_util.h"
[email protected]bf828982013-08-14 18:01:4724#include "base/memory/weak_ptr.h"
Eric Orthf4db66a2019-02-19 21:35:3325#include "base/optional.h"
[email protected]a34f61ee2014-03-18 20:59:4926#include "base/run_loop.h"
Avi Drissman4365a4782018-12-28 19:26:2427#include "base/stl_util.h"
Bence Békyd74f4382018-02-20 18:26:1928#include "base/strings/string_piece.h"
[email protected]125ef482013-06-11 18:32:4729#include "base/strings/string_util.h"
Matt Menked732ea42019-03-08 12:05:0030#include "base/strings/stringprintf.h"
[email protected]750b2f3c2013-06-07 18:41:0531#include "base/strings/utf_string_conversions.h"
Douglas Creager3cb042052018-11-06 23:08:5232#include "base/test/metrics/histogram_tester.h"
Matt Menke166443c2019-05-24 18:45:5933#include "base/test/scoped_feature_list.h"
Matt Menkeecfecfc72019-02-05 19:15:2834#include "base/test/scoped_task_environment.h"
Douglas Creager134b52e2018-11-09 18:00:1435#include "base/test/simple_test_clock.h"
36#include "base/test/simple_test_tick_clock.h"
[email protected]f36a8132011-09-02 18:36:3337#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3538#include "base/threading/thread_task_runner_handle.h"
Matt Menke5062be22019-05-01 17:50:2439#include "build/build_config.h"
[email protected]277d5942010-08-11 21:02:3540#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0741#include "net/base/chunked_upload_data_stream.h"
Bence Békya25e3f72018-02-13 21:13:3942#include "net/base/completion_once_callback.h"
mmenkecbc2b712014-10-09 20:29:0743#include "net/base/elements_upload_data_stream.h"
Matt Menke166443c2019-05-24 18:45:5944#include "net/base/features.h"
Eric Orthf4db66a2019-02-19 21:35:3345#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3746#include "net/base/ip_endpoint.h"
[email protected]58e32bb2013-01-21 18:23:2547#include "net/base/load_timing_info.h"
48#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2449#include "net/base/net_errors.h"
Matt Menkebdf777802019-04-22 19:38:5950#include "net/base/privacy_mode.h"
tbansal28e68f82016-02-04 02:56:1551#include "net/base/proxy_delegate.h"
Lily Houghton582d4622018-01-22 22:43:4052#include "net/base/proxy_server.h"
[email protected]ac790b42009-12-02 04:31:3153#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5254#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1555#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0656#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2157#include "net/base/upload_file_element_reader.h"
Bence Béky230ac612017-08-30 19:17:0858#include "net/cert/cert_status_flags.h"
[email protected]6e7845ae2013-03-29 21:48:1159#include "net/cert/mock_cert_verifier.h"
[email protected]f2cb3cf2013-03-21 01:40:5360#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2461#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1262#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0063#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2964#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1965#include "net/http/http_auth_scheme.h"
[email protected]0877e3d2009-10-17 22:29:5766#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5267#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5668#include "net/http/http_network_session_peer.h"
Matt Menke6e879bd2019-03-18 17:26:0469#include "net/http/http_proxy_connect_job.h"
Adam Rice425cf122015-01-19 06:18:2470#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1371#include "net/http/http_response_info.h"
[email protected]17291a022011-10-10 07:32:5372#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5773#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3874#include "net/http/http_stream_factory.h"
[email protected]c41737d2014-05-14 07:47:1975#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0776#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0077#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1978#include "net/log/net_log_source.h"
vishal.b62985ca92015-04-17 08:45:5179#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4680#include "net/log/test_net_log_util.h"
Lily Houghton582d4622018-01-22 22:43:4081#include "net/proxy_resolution/mock_proxy_resolver.h"
82#include "net/proxy_resolution/proxy_config_service_fixed.h"
83#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0384#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4085#include "net/proxy_resolution/proxy_resolver.h"
86#include "net/proxy_resolution/proxy_resolver_factory.h"
[email protected]f7984fc62009-06-22 23:26:4487#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1588#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0389#include "net/socket/client_socket_pool_manager.h"
Matt Menked6fd2a52019-03-20 06:14:3690#include "net/socket/connect_job.h"
ttuttle1f2d7e92015-04-28 16:17:4791#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0292#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0793#include "net/socket/next_proto.h"
Paul Jensena457017a2018-01-19 23:52:0494#include "net/socket/socket_tag.h"
[email protected]f7984fc62009-06-22 23:26:4495#include "net/socket/socket_test_util.h"
Matt Menke4b412da2019-01-25 19:31:1296#include "net/socket/socks_connect_job.h"
[email protected]f7984fc62009-06-22 23:26:4497#include "net/socket/ssl_client_socket.h"
Bence Béky94658bf2018-05-11 19:22:5898#include "net/spdy/spdy_session.h"
99#include "net/spdy/spdy_session_pool.h"
100#include "net/spdy/spdy_test_util_common.h"
David Benjamin2eb827f2019-04-29 18:31:04101#include "net/ssl/client_cert_identity_test_util.h"
[email protected]536fd0b2013-03-14 17:41:57102#include "net/ssl/ssl_cert_request_info.h"
David Benjaminef2f2a5a2019-07-16 19:21:31103#include "net/ssl/ssl_config.h"
[email protected]e86839fd2013-08-14 18:29:03104#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:57105#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:54106#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:11107#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:01108#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:43109#include "net/test/test_data_directory.h"
Bence Béky98447b12018-05-08 03:14:01110#include "net/test/test_with_scoped_task_environment.h"
Victor Vasiliev27cc7712019-01-24 11:50:14111#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
[email protected]baee31a2018-01-18 06:10:23112#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Matt Menked732ea42019-03-08 12:05:00113#include "net/url_request/static_http_user_agent_settings.h"
[email protected]831e4a32013-11-14 02:14:44114#include "net/websockets/websocket_handshake_stream_base.h"
Bence Békydca6bd92018-01-30 13:43:06115#include "net/websockets/websocket_test_util.h"
bncf4588402015-11-24 13:33:18116#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:52117#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:15118#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:27119#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:52120
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37121#if defined(NTLM_PORTABLE)
122#include "base/base64.h"
123#include "net/ntlm/ntlm_test_data.h"
124#endif
125
Douglas Creager3cb042052018-11-06 23:08:52126#if BUILDFLAG(ENABLE_REPORTING)
127#include "net/network_error_logging/network_error_logging_service.h"
128#include "net/network_error_logging/network_error_logging_test_util.h"
Douglas Creager134b52e2018-11-09 18:00:14129#include "net/reporting/reporting_cache.h"
Lily Chenfc92ff42019-05-06 22:59:10130#include "net/reporting/reporting_endpoint.h"
Douglas Creager134b52e2018-11-09 18:00:14131#include "net/reporting/reporting_header_parser.h"
132#include "net/reporting/reporting_service.h"
133#include "net/reporting/reporting_test_util.h"
Douglas Creager3cb042052018-11-06 23:08:52134#endif // BUILDFLAG(ENABLE_REPORTING)
135
robpercival214763f2016-07-01 23:27:01136using net::test::IsError;
137using net::test::IsOk;
138
[email protected]ad65a3e2013-12-25 18:18:01139using base::ASCIIToUTF16;
140
David Benjamin3b94b0f2019-04-25 23:07:52141using testing::AnyOf;
142
initial.commit586acc5fe2008-07-26 22:42:52143//-----------------------------------------------------------------------------
144
ttuttle859dc7a2015-04-23 19:42:29145namespace net {
146
[email protected]13c8a092010-07-29 06:15:44147namespace {
148
[email protected]42cba2fb2013-03-29 19:58:57149const base::string16 kBar(ASCIIToUTF16("bar"));
150const base::string16 kBar2(ASCIIToUTF16("bar2"));
151const base::string16 kBar3(ASCIIToUTF16("bar3"));
152const base::string16 kBaz(ASCIIToUTF16("baz"));
153const base::string16 kFirst(ASCIIToUTF16("first"));
154const base::string16 kFoo(ASCIIToUTF16("foo"));
155const base::string16 kFoo2(ASCIIToUTF16("foo2"));
156const base::string16 kFoo3(ASCIIToUTF16("foo3"));
157const base::string16 kFou(ASCIIToUTF16("fou"));
158const base::string16 kSecond(ASCIIToUTF16("second"));
[email protected]42cba2fb2013-03-29 19:58:57159const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44160
bnc2df4b522016-07-08 18:17:43161const char kAlternativeServiceHttpHeader[] =
162 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
163
ttuttle859dc7a2015-04-23 19:42:29164int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40165 return session
166 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
167 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29168 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02169}
170
ttuttle859dc7a2015-04-23 19:42:29171bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
Matt Menked23ab952019-03-06 00:24:40172 return session
173 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
174 ProxyServer::Direct())
ttuttle859dc7a2015-04-23 19:42:29175 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52176}
177
[email protected]f3da152d2012-06-02 01:00:57178// Takes in a Value created from a NetLogHttpResponseParameter, and returns
179// a JSONified list of headers as a single string. Uses single quotes instead
Eric Roman79cc7552019-07-19 02:17:54180// of double quotes for easier comparison.
181std::string GetHeaders(const base::Value& params) {
182 if (!params.is_dict())
183 return "";
184 const base::Value* header_list = params.FindListKey("headers");
185 if (!header_list)
186 return "";
187 std::string headers;
188 base::JSONWriter::Write(*header_list, &headers);
189 base::ReplaceChars(headers, "\"", "'", &headers);
190 return headers;
[email protected]f3da152d2012-06-02 01:00:57191}
192
[email protected]029c83b62013-01-24 05:28:20193// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
194// used.
ttuttle859dc7a2015-04-23 19:42:29195void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20196 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19197 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25198
[email protected]029c83b62013-01-24 05:28:20199 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
200 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
201
ttuttle859dc7a2015-04-23 19:42:29202 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20203 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25204
205 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25206
[email protected]3b23a222013-05-15 21:33:25207 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25208 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
209 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25210 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25211}
212
[email protected]029c83b62013-01-24 05:28:20213// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
214// used.
ttuttle859dc7a2015-04-23 19:42:29215void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25216 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20217 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19218 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20219
220 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
221 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
222
ttuttle859dc7a2015-04-23 19:42:29223 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
224 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20225 EXPECT_LE(load_timing_info.connect_timing.connect_end,
226 load_timing_info.send_start);
227
228 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20229
[email protected]3b23a222013-05-15 21:33:25230 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20231 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
232 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25233 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20234}
235
236// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
237// used.
ttuttle859dc7a2015-04-23 19:42:29238void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20239 EXPECT_TRUE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19240 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20241
ttuttle859dc7a2015-04-23 19:42:29242 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20243
244 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
245 EXPECT_LE(load_timing_info.proxy_resolve_start,
246 load_timing_info.proxy_resolve_end);
247 EXPECT_LE(load_timing_info.proxy_resolve_end,
248 load_timing_info.send_start);
249 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20250
[email protected]3b23a222013-05-15 21:33:25251 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20252 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
253 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25254 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20255}
256
257// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
258// used.
ttuttle859dc7a2015-04-23 19:42:29259void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20260 int connect_timing_flags) {
261 EXPECT_FALSE(load_timing_info.socket_reused);
mikecironef22f9812016-10-04 03:40:19262 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20263
264 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
265 EXPECT_LE(load_timing_info.proxy_resolve_start,
266 load_timing_info.proxy_resolve_end);
267 EXPECT_LE(load_timing_info.proxy_resolve_end,
268 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29269 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
270 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20271 EXPECT_LE(load_timing_info.connect_timing.connect_end,
272 load_timing_info.send_start);
273
274 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20275
[email protected]3b23a222013-05-15 21:33:25276 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20277 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
278 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25279 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25280}
281
Matt Menke2436b2f2018-12-11 18:07:11282// ProxyResolver that records URLs passed to it, and that can be told what
283// result to return.
284class CapturingProxyResolver : public ProxyResolver {
285 public:
286 CapturingProxyResolver()
287 : proxy_server_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
288 ~CapturingProxyResolver() override = default;
289
290 int GetProxyForURL(const GURL& url,
291 ProxyInfo* results,
292 CompletionOnceCallback callback,
293 std::unique_ptr<Request>* request,
294 const NetLogWithSource& net_log) override {
295 results->UseProxyServer(proxy_server_);
296 resolved_.push_back(url);
297 return OK;
298 }
299
300 // Sets whether the resolver should use direct connections, instead of a
301 // proxy.
302 void set_proxy_server(ProxyServer proxy_server) {
303 proxy_server_ = proxy_server;
304 }
305
306 const std::vector<GURL>& resolved() const { return resolved_; }
307
308 private:
309 std::vector<GURL> resolved_;
310
311 ProxyServer proxy_server_;
312
313 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
314};
315
316class CapturingProxyResolverFactory : public ProxyResolverFactory {
317 public:
318 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
319 : ProxyResolverFactory(false), resolver_(resolver) {}
320
321 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
322 std::unique_ptr<ProxyResolver>* resolver,
323 CompletionOnceCallback callback,
324 std::unique_ptr<Request>* request) override {
325 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
326 return OK;
327 }
328
329 private:
330 ProxyResolver* resolver_;
331};
332
danakj1fd259a02016-04-16 03:17:09333std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42334 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34335 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14336}
337
xunjieli96f2a402017-06-05 17:24:27338class FailingProxyResolverFactory : public ProxyResolverFactory {
339 public:
340 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
341
342 // ProxyResolverFactory override.
Lily Houghton99597862018-03-07 16:40:42343 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
344 std::unique_ptr<ProxyResolver>* result,
Bence Békycc5b88a2018-05-25 20:24:17345 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:42346 std::unique_ptr<Request>* request) override {
xunjieli96f2a402017-06-05 17:24:27347 return ERR_PAC_SCRIPT_FAILED;
348 }
349};
350
David Benjamin5cb91132018-04-06 05:54:49351class TestSSLConfigService : public SSLConfigService {
352 public:
353 explicit TestSSLConfigService(const SSLConfig& config) : config_(config) {}
Ryan Sleevib8449e02018-07-15 04:31:07354 ~TestSSLConfigService() override = default;
David Benjamin5cb91132018-04-06 05:54:49355
356 void GetSSLConfig(SSLConfig* config) override { *config = config_; }
357
Nick Harper89bc7212018-07-31 19:07:57358 bool CanShareConnectionWithClientCerts(
359 const std::string& hostname) const override {
360 return false;
361 }
362
David Benjaminef2f2a5a2019-07-16 19:21:31363 void UpdateSSLConfigAndNotify(const SSLConfig& config) {
364 config_ = config;
365 NotifySSLConfigChange();
366 }
367
David Benjamin5cb91132018-04-06 05:54:49368 private:
David Benjamin5cb91132018-04-06 05:54:49369 SSLConfig config_;
370};
371
[email protected]448d4ca52012-03-04 04:12:23372} // namespace
373
Bence Béky98447b12018-05-08 03:14:01374class HttpNetworkTransactionTest : public PlatformTest,
375 public WithScopedTaskEnvironment {
[email protected]483fa202013-05-14 01:07:03376 public:
bncd16676a2016-07-20 16:23:01377 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03378 // Important to restore the per-pool limit first, since the pool limit must
379 // always be greater than group limit, and the tests reduce both limits.
380 ClientSocketPoolManager::set_max_sockets_per_pool(
381 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
382 ClientSocketPoolManager::set_max_sockets_per_group(
383 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
384 }
385
[email protected]e3ceb682011-06-28 23:55:46386 protected:
[email protected]23e482282013-06-14 16:08:02387 HttpNetworkTransactionTest()
Andrew Comminos517a92c2019-01-14 17:49:56388 : WithScopedTaskEnvironment(
Gabriel Charette29f1e2c62019-07-15 21:30:35389 base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME_AND_NOW),
Matt Menked6fd2a52019-03-20 06:14:36390 dummy_connect_job_params_(
391 nullptr /* client_socket_factory */,
392 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:40393 nullptr /* http_auth_cache */,
394 nullptr /* http_auth_handler_factory */,
395 nullptr /* spdy_session_pool */,
Matt Menkeb5fb42b2019-03-22 17:26:13396 nullptr /* quic_supported_versions */,
Matt Menkeb88837e2019-03-20 11:50:40397 nullptr /* quic_stream_factory */,
Matt Menked6fd2a52019-03-20 06:14:36398 nullptr /* proxy_delegate */,
399 nullptr /* http_user_agent_settings */,
400 SSLClientSocketContext(),
401 SSLClientSocketContext(),
402 nullptr /* socket_performance_watcher_factory */,
403 nullptr /* network_quality_estimator */,
404 nullptr /* net_log */,
405 nullptr /* websocket_endpoint_lock_manager */),
Andrew Comminos517a92c2019-01-14 17:49:56406 ssl_(ASYNC, OK),
bnc032658ba2016-09-26 18:17:15407 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03408 HttpNetworkSession::NORMAL_SOCKET_POOL)),
409 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
410 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bnca86731e2017-04-17 12:31:28411 session_deps_.enable_http2_alternative_service = true;
[email protected]483fa202013-05-14 01:07:03412 }
[email protected]bb88e1d32013-05-03 23:11:07413
[email protected]e3ceb682011-06-28 23:55:46414 struct SimpleGetHelperResult {
415 int rv;
416 std::string status_line;
417 std::string response_data;
sclittlefb249892015-09-10 21:33:22418 int64_t total_received_bytes;
419 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25420 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47421 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59422 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46423 };
424
dcheng67be2b1f2014-10-27 21:47:29425 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50426 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55427 base::RunLoop().RunUntilIdle();
Andrew Comminos517a92c2019-01-14 17:49:56428 // Set an initial delay to ensure that the first call to TimeTicks::Now()
429 // before incrementing the counter does not return a null value.
430 FastForwardBy(TimeDelta::FromSeconds(1));
[email protected]2ff8b312010-04-26 22:20:54431 }
432
dcheng67be2b1f2014-10-27 21:47:29433 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50434 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55435 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09436 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55437 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09438 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50439 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55440 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09441 }
442
Andrew Comminos1f2ff1cc2018-12-14 05:22:38443 void Check100ResponseTiming(bool use_spdy);
444
[email protected]202965992011-12-07 23:04:51445 // Either |write_failure| specifies a write failure or |read_failure|
446 // specifies a read failure when using a reused socket. In either case, the
447 // failure should cause the network transaction to resend the request, and the
448 // other argument should be NULL.
449 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
450 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52451
[email protected]a34f61ee2014-03-18 20:59:49452 // Either |write_failure| specifies a write failure or |read_failure|
453 // specifies a read failure when using a reused socket. In either case, the
454 // failure should cause the network transaction to resend the request, and the
455 // other argument should be NULL.
456 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10457 const MockRead* read_failure,
458 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49459
Ryan Sleevib8d7ea02018-05-07 20:01:01460 SimpleGetHelperResult SimpleGetHelperForData(
461 base::span<StaticSocketDataProvider*> providers) {
[email protected]ff007e162009-05-23 09:13:15462 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52463
[email protected]ff007e162009-05-23 09:13:15464 HttpRequestInfo request;
465 request.method = "GET";
bncce36dca22015-04-21 22:11:23466 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10467 request.traffic_annotation =
468 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:52469
vishal.b62985ca92015-04-17 08:45:51470 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07471 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09472 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16473 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:27474
Ryan Sleevib8d7ea02018-05-07 20:01:01475 for (auto* provider : providers) {
476 session_deps_.socket_factory->AddSocketDataProvider(provider);
[email protected]5a60c8b2011-10-19 20:14:29477 }
initial.commit586acc5fe2008-07-26 22:42:52478
[email protected]49639fa2011-12-20 23:22:41479 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52480
eroman24bc6a12015-05-06 19:55:48481 EXPECT_TRUE(log.bound().IsCapturing());
bnc691fda62016-08-12 00:43:16482 int rv = trans.Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01483 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52484
[email protected]ff007e162009-05-23 09:13:15485 out.rv = callback.WaitForResult();
bnc691fda62016-08-12 00:43:16486 out.total_received_bytes = trans.GetTotalReceivedBytes();
487 out.total_sent_bytes = trans.GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25488
489 // Even in the failure cases that use this function, connections are always
490 // successfully established before the error.
bnc691fda62016-08-12 00:43:16491 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
[email protected]58e32bb2013-01-21 18:23:25492 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
493
[email protected]ff007e162009-05-23 09:13:15494 if (out.rv != OK)
495 return out;
496
bnc691fda62016-08-12 00:43:16497 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50498 // Can't use ASSERT_* inside helper functions like this, so
499 // return an error.
wezca1070932016-05-26 20:30:52500 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50501 out.rv = ERR_UNEXPECTED;
502 return out;
503 }
[email protected]ff007e162009-05-23 09:13:15504 out.status_line = response->headers->GetStatusLine();
505
Tsuyoshi Horo01faed62019-02-20 22:11:37506 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
507 EXPECT_EQ(80, response->remote_endpoint.port());
[email protected]6d81b482011-02-22 19:47:19508
ttuttled9dbc652015-09-29 20:00:59509 bool got_endpoint =
bnc691fda62016-08-12 00:43:16510 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
ttuttled9dbc652015-09-29 20:00:59511 EXPECT_EQ(got_endpoint,
512 out.remote_endpoint_after_start.address().size() > 0);
513
bnc691fda62016-08-12 00:43:16514 rv = ReadTransaction(&trans, &out.response_data);
robpercival214763f2016-07-01 23:27:01515 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40516
Eric Roman79cc7552019-07-19 02:17:54517 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:39518 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00519 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
520 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:39521 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:00522 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
523 NetLogEventPhase::NONE);
[email protected]ff007e162009-05-23 09:13:15524
Eric Roman79cc7552019-07-19 02:17:54525 EXPECT_EQ("GET / HTTP/1.1\r\n",
526 GetStringValueFromParams(entries[pos], "line"));
[email protected]f3da152d2012-06-02 01:00:57527
[email protected]79e1fd62013-06-20 06:50:04528 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:16529 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:04530 std::string value;
531 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23532 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04533 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
534 EXPECT_EQ("keep-alive", value);
535
bncce36dca22015-04-21 22:11:23536 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
Eric Roman79cc7552019-07-19 02:17:54537 GetHeaders(entries[pos].params));
[email protected]3deb9a52010-11-11 00:24:40538
bnc691fda62016-08-12 00:43:16539 out.total_received_bytes = trans.GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22540 // The total number of sent bytes should not have changed.
bnc691fda62016-08-12 00:43:16541 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
sclittlefb249892015-09-10 21:33:22542
bnc691fda62016-08-12 00:43:16543 trans.GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47544 return out;
[email protected]ff007e162009-05-23 09:13:15545 }
initial.commit586acc5fe2008-07-26 22:42:52546
Ryan Sleevib8d7ea02018-05-07 20:01:01547 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
sclittlefb249892015-09-10 21:33:22548 MockWrite data_writes[] = {
549 MockWrite("GET / HTTP/1.1\r\n"
550 "Host: www.example.org\r\n"
551 "Connection: keep-alive\r\n\r\n"),
552 };
[email protected]5a60c8b2011-10-19 20:14:29553
Ryan Sleevib8d7ea02018-05-07 20:01:01554 StaticSocketDataProvider reads(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:22555 StaticSocketDataProvider* data[] = {&reads};
Ryan Sleevib8d7ea02018-05-07 20:01:01556 SimpleGetHelperResult out = SimpleGetHelperForData(data);
sclittlefb249892015-09-10 21:33:22557
Ryan Sleevib8d7ea02018-05-07 20:01:01558 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
sclittlefb249892015-09-10 21:33:22559 return out;
[email protected]b8015c42013-12-24 15:18:19560 }
561
bnc032658ba2016-09-26 18:17:15562 void AddSSLSocketData() {
563 ssl_.next_proto = kProtoHTTP2;
Ryan Sleevi4f832092017-11-21 23:25:49564 ssl_.ssl_info.cert =
565 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
566 ASSERT_TRUE(ssl_.ssl_info.cert);
bnc032658ba2016-09-26 18:17:15567 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
568 }
569
[email protected]ff007e162009-05-23 09:13:15570 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
571 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52572
[email protected]ff007e162009-05-23 09:13:15573 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07574
[email protected]bb88e1d32013-05-03 23:11:07575 void CheckErrorIsPassedBack(int error, IoMode mode);
576
Matt Menked6fd2a52019-03-20 06:14:36577 const CommonConnectJobParams dummy_connect_job_params_;
578
Douglas Creager134b52e2018-11-09 18:00:14579 // These clocks are defined here, even though they're only used in the
580 // Reporting tests below, since they need to be destroyed after
581 // |session_deps_|.
582 base::SimpleTestClock clock_;
583 base::SimpleTestTickClock tick_clock_;
584
[email protected]4bd46222013-05-14 19:32:23585 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07586 SpdySessionDependencies session_deps_;
bnc032658ba2016-09-26 18:17:15587 SSLSocketDataProvider ssl_;
[email protected]483fa202013-05-14 01:07:03588
589 // Original socket limits. Some tests set these. Safest to always restore
590 // them once each test has been run.
591 int old_max_group_sockets_;
592 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15593};
[email protected]231d5a32008-09-13 00:45:27594
[email protected]448d4ca52012-03-04 04:12:23595namespace {
596
ryansturm49a8cb12016-06-15 16:51:09597class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27598 public:
ryansturm49a8cb12016-06-15 16:51:09599 BeforeHeadersSentHandler()
600 : observed_before_headers_sent_with_proxy_(false),
601 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27602
ryansturm49a8cb12016-06-15 16:51:09603 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
604 HttpRequestHeaders* request_headers) {
605 observed_before_headers_sent_ = true;
606 if (!proxy_info.is_http() && !proxy_info.is_https() &&
607 !proxy_info.is_quic()) {
608 return;
609 }
610 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27611 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
612 }
613
ryansturm49a8cb12016-06-15 16:51:09614 bool observed_before_headers_sent_with_proxy() const {
615 return observed_before_headers_sent_with_proxy_;
616 }
617
618 bool observed_before_headers_sent() const {
619 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27620 }
621
622 std::string observed_proxy_server_uri() const {
623 return observed_proxy_server_uri_;
624 }
625
626 private:
ryansturm49a8cb12016-06-15 16:51:09627 bool observed_before_headers_sent_with_proxy_;
628 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27629 std::string observed_proxy_server_uri_;
630
ryansturm49a8cb12016-06-15 16:51:09631 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27632};
633
[email protected]15a5ccf82008-10-23 19:57:43634// Fill |str| with a long header list that consumes >= |size| bytes.
635void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51636 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19637 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
638 const int sizeof_row = strlen(row);
639 const int num_rows = static_cast<int>(
640 ceil(static_cast<float>(size) / sizeof_row));
641 const int sizeof_data = num_rows * sizeof_row;
642 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43643 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51644
[email protected]4ddaf2502008-10-23 18:26:19645 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43646 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19647}
648
thakis84dff942015-07-28 20:47:38649#if defined(NTLM_PORTABLE)
Zentaro Kavanagh6ccee512017-09-28 18:34:09650uint64_t MockGetMSTime() {
651 // Tue, 23 May 2017 20:13:07 +0000
652 return 131400439870000000;
653}
654
[email protected]385a4672009-03-11 22:21:29655// Alternative functions that eliminate randomness and dependency on the local
656// host name so that the generated NTLM messages are reproducible.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37657void MockGenerateRandom(uint8_t* output, size_t n) {
658 // This is set to 0xaa because the client challenge for testing in
659 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
660 memset(output, 0xaa, n);
[email protected]385a4672009-03-11 22:21:29661}
662
[email protected]fe2bc6a2009-03-23 16:52:20663std::string MockGetHostName() {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:37664 return ntlm::test::kHostnameAscii;
[email protected]385a4672009-03-11 22:21:29665}
thakis84dff942015-07-28 20:47:38666#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29667
Matt Menked6fd2a52019-03-20 06:14:36668class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31669 public:
Matt Menked6fd2a52019-03-20 06:14:36670 explicit CaptureGroupIdTransportSocketPool(
671 const CommonConnectJobParams* common_connect_job_params)
672 : TransportClientSocketPool(0,
673 0,
674 base::TimeDelta(),
Matt Menkeaafff542019-04-22 22:09:36675 ProxyServer::Direct(),
676 false /* is_for_websockets */,
Matt Menked6fd2a52019-03-20 06:14:36677 common_connect_job_params,
678 nullptr /* ssl_config_service */) {}
[email protected]e60e47a2010-07-14 03:37:18679
Matt Menkef6edce752019-03-19 17:21:56680 const ClientSocketPool::GroupId& last_group_id_received() const {
681 return last_group_id_;
[email protected]d80a4322009-08-14 07:07:49682 }
683
Tarun Bansal162eabe52018-01-20 01:16:39684 bool socket_requested() const { return socket_requested_; }
685
Matt Menke28ac03e2019-02-25 22:25:50686 int RequestSocket(
Matt Menkef6edce752019-03-19 17:21:56687 const ClientSocketPool::GroupId& group_id,
Matt Menkebd12b7e2019-03-25 21:12:03688 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Matt Menkef09e64c2019-04-23 22:16:28689 const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menke28ac03e2019-02-25 22:25:50690 RequestPriority priority,
691 const SocketTag& socket_tag,
692 ClientSocketPool::RespectLimits respect_limits,
693 ClientSocketHandle* handle,
694 CompletionOnceCallback callback,
695 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
696 const NetLogWithSource& net_log) override {
Matt Menkef6edce752019-03-19 17:21:56697 last_group_id_ = group_id;
Tarun Bansal162eabe52018-01-20 01:16:39698 socket_requested_ = true;
[email protected]04e5be32009-06-26 20:00:31699 return ERR_IO_PENDING;
700 }
Matt Menkef6edce752019-03-19 17:21:56701 void CancelRequest(const ClientSocketPool::GroupId& group_id,
Matt Menke7eb405e2019-04-25 20:48:21702 ClientSocketHandle* handle,
703 bool cancel_connect_job) override {}
Matt Menkef6edce752019-03-19 17:21:56704 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
danakj1fd259a02016-04-16 03:17:09705 std::unique_ptr<StreamSocket> socket,
Matt Menkebf3c767d2019-04-15 23:28:24706 int64_t generation) override {}
dmichaeld6e570d2014-12-18 22:30:57707 void CloseIdleSockets() override {}
Matt Menkef6edce752019-03-19 17:21:56708 void CloseIdleSocketsInGroup(
709 const ClientSocketPool::GroupId& group_id) override {}
dmichaeld6e570d2014-12-18 22:30:57710 int IdleSocketCount() const override { return 0; }
Matt Menkef6edce752019-03-19 17:21:56711 size_t IdleSocketCountInGroup(
712 const ClientSocketPool::GroupId& group_id) const override {
[email protected]04e5be32009-06-26 20:00:31713 return 0;
714 }
Matt Menkef6edce752019-03-19 17:21:56715 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
dmichaeld6e570d2014-12-18 22:30:57716 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31717 return LOAD_STATE_IDLE;
718 }
[email protected]d80a4322009-08-14 07:07:49719
720 private:
Matt Menkef6edce752019-03-19 17:21:56721 ClientSocketPool::GroupId last_group_id_;
Tarun Bansal162eabe52018-01-20 01:16:39722 bool socket_requested_ = false;
[email protected]04e5be32009-06-26 20:00:31723};
724
[email protected]231d5a32008-09-13 00:45:27725//-----------------------------------------------------------------------------
726
[email protected]79cb5c12011-09-12 13:12:04727// Helper functions for validating that AuthChallengeInfo's are correctly
728// configured for common cases.
Emily Starkf2c9bbd2019-04-09 17:08:58729bool CheckBasicServerAuth(
730 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04731 if (!auth_challenge)
732 return false;
733 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43734 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04735 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19736 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04737 return true;
738}
739
David Benjamin2eb827f2019-04-29 18:31:04740bool CheckBasicSecureServerAuth(
741 const base::Optional<AuthChallengeInfo>& auth_challenge) {
742 if (!auth_challenge)
743 return false;
744 EXPECT_FALSE(auth_challenge->is_proxy);
745 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
746 EXPECT_EQ("MyRealm1", auth_challenge->realm);
747 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
748 return true;
749}
750
Emily Starkf2c9bbd2019-04-09 17:08:58751bool CheckBasicProxyAuth(
752 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04753 if (!auth_challenge)
754 return false;
755 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43756 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
757 EXPECT_EQ("MyRealm1", auth_challenge->realm);
758 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
759 return true;
760}
761
Emily Starkf2c9bbd2019-04-09 17:08:58762bool CheckBasicSecureProxyAuth(
763 const base::Optional<AuthChallengeInfo>& auth_challenge) {
asanka098c0092016-06-16 20:18:43764 if (!auth_challenge)
765 return false;
766 EXPECT_TRUE(auth_challenge->is_proxy);
767 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04768 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19769 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04770 return true;
771}
772
Emily Starkf2c9bbd2019-04-09 17:08:58773bool CheckDigestServerAuth(
774 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04775 if (!auth_challenge)
776 return false;
777 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43778 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04779 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19780 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04781 return true;
782}
783
thakis84dff942015-07-28 20:47:38784#if defined(NTLM_PORTABLE)
Emily Starkf2c9bbd2019-04-09 17:08:58785bool CheckNTLMServerAuth(
786 const base::Optional<AuthChallengeInfo>& auth_challenge) {
[email protected]79cb5c12011-09-12 13:12:04787 if (!auth_challenge)
788 return false;
789 EXPECT_FALSE(auth_challenge->is_proxy);
Zentaro Kavanagh1890a3d2018-01-29 19:52:55790 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04791 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19792 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04793 return true;
794}
David Benjamin5cb91132018-04-06 05:54:49795
Emily Starkf2c9bbd2019-04-09 17:08:58796bool CheckNTLMProxyAuth(
797 const base::Optional<AuthChallengeInfo>& auth_challenge) {
David Benjamin5cb91132018-04-06 05:54:49798 if (!auth_challenge)
799 return false;
800 EXPECT_TRUE(auth_challenge->is_proxy);
801 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
802 EXPECT_EQ(std::string(), auth_challenge->realm);
803 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
804 return true;
805}
thakis84dff942015-07-28 20:47:38806#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04807
[email protected]448d4ca52012-03-04 04:12:23808} // namespace
809
bncd16676a2016-07-20 16:23:01810TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09811 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:16812 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]231d5a32008-09-13 00:45:27813}
814
bncd16676a2016-07-20 16:23:01815TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27816 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35817 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
818 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06819 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27820 };
Ryan Sleevib8d7ea02018-05-07 20:01:01821 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01822 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27823 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
824 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01825 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22826 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47827 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59828
829 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27830}
831
832// Response with no status line.
bncd16676a2016-07-20 16:23:01833TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27834 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35835 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06836 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27837 };
Ryan Sleevib8d7ea02018-05-07 20:01:01838 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41839 EXPECT_THAT(out.rv, IsOk());
840 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
841 EXPECT_EQ("hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01842 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41843 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27844}
845
mmenkea7da6da2016-09-01 21:56:52846// Response with no status line, and a weird port. Should fail by default.
847TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
848 MockRead data_reads[] = {
849 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
850 };
851
Ryan Sleevib8d7ea02018-05-07 20:01:01852 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52853 session_deps_.socket_factory->AddSocketDataProvider(&data);
854
855 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
856
krasinc06a72a2016-12-21 03:42:46857 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58858 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19859 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52860
mmenkea7da6da2016-09-01 21:56:52861 request.method = "GET";
862 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10863 request.traffic_annotation =
864 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
865
mmenkea7da6da2016-09-01 21:56:52866 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20867 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52868 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
869}
870
Shivani Sharmafdcaefd2017-11-02 00:12:26871// Tests that request info can be destroyed after the headers phase is complete.
872TEST_F(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
873 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
874 auto trans =
875 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
876
877 MockRead data_reads[] = {
878 MockRead("HTTP/1.0 200 OK\r\n"), MockRead("Connection: keep-alive\r\n"),
879 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, 0),
880 };
Ryan Sleevib8d7ea02018-05-07 20:01:01881 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Shivani Sharmafdcaefd2017-11-02 00:12:26882 session_deps_.socket_factory->AddSocketDataProvider(&data);
883
884 TestCompletionCallback callback;
885
886 {
887 auto request = std::make_unique<HttpRequestInfo>();
888 request->method = "GET";
889 request->url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:10890 request->traffic_annotation =
891 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Shivani Sharmafdcaefd2017-11-02 00:12:26892
893 int rv =
894 trans->Start(request.get(), callback.callback(), NetLogWithSource());
895
896 EXPECT_THAT(callback.GetResult(rv), IsOk());
897 } // Let request info be destroyed.
898
899 trans.reset();
900}
901
mmenkea7da6da2016-09-01 21:56:52902// Response with no status line, and a weird port. Option to allow weird ports
903// enabled.
904TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPortAllowed) {
905 MockRead data_reads[] = {
906 MockRead("hello world"), MockRead(SYNCHRONOUS, OK),
907 };
908
Ryan Sleevib8d7ea02018-05-07 20:01:01909 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
mmenkea7da6da2016-09-01 21:56:52910 session_deps_.socket_factory->AddSocketDataProvider(&data);
911 session_deps_.http_09_on_non_default_ports_enabled = true;
912 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
913
krasinc06a72a2016-12-21 03:42:46914 HttpRequestInfo request;
bnc87dcefc2017-05-25 12:47:58915 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:19916 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenkea7da6da2016-09-01 21:56:52917
mmenkea7da6da2016-09-01 21:56:52918 request.method = "GET";
919 request.url = GURL("http://www.example.com:2000/");
Ramin Halavatib5e433e62018-02-07 07:41:10920 request.traffic_annotation =
921 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
922
mmenkea7da6da2016-09-01 21:56:52923 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:20924 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea7da6da2016-09-01 21:56:52925 EXPECT_THAT(callback.GetResult(rv), IsOk());
926
927 const HttpResponseInfo* info = trans->GetResponseInfo();
928 ASSERT_TRUE(info->headers);
929 EXPECT_EQ("HTTP/0.9 200 OK", info->headers->GetStatusLine());
930
931 // Don't bother to read the body - that's verified elsewhere, important thing
932 // is that the option to allow HTTP/0.9 on non-default ports is respected.
933}
934
[email protected]231d5a32008-09-13 00:45:27935// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01936TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27937 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35938 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06939 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27940 };
Ryan Sleevib8d7ea02018-05-07 20:01:01941 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01942 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27943 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
944 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01945 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22946 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27947}
948
949// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01950TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27951 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35952 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06953 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27954 };
Ryan Sleevib8d7ea02018-05-07 20:01:01955 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01956 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27957 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
958 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01959 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22960 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27961}
962
963// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01964TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27965 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35966 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06967 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27968 };
Ryan Sleevib8d7ea02018-05-07 20:01:01969 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41970 EXPECT_THAT(out.rv, IsOk());
971 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
972 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01973 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:41974 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27975}
976
977// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01978TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27979 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35980 MockRead("\n"),
981 MockRead("\n"),
982 MockRead("Q"),
983 MockRead("J"),
984 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06985 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27986 };
Ryan Sleevib8d7ea02018-05-07 20:01:01987 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:01988 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27989 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
990 EXPECT_EQ("DATA", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:01991 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:22992 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27993}
994
995// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01996TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27997 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35998 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06999 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:271000 };
Ryan Sleevib8d7ea02018-05-07 20:01:011001 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411002 EXPECT_THAT(out.rv, IsOk());
1003 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1004 EXPECT_EQ("HTT", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011005 int64_t reads_size = CountReadBytes(data_reads);
mmenkea2dcd3bf2016-08-16 21:49:411006 EXPECT_EQ(reads_size, out.total_received_bytes);
initial.commit586acc5fe2008-07-26 22:42:521007}
1008
[email protected]f9d44aa2008-09-23 23:57:171009// Simulate a 204 response, lacking a Content-Length header, sent over a
1010// persistent connection. The response should still terminate since a 204
1011// cannot have a response body.
bncd16676a2016-07-20 16:23:011012TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:191013 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:171014 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351015 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:191016 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:061017 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:171018 };
Ryan Sleevib8d7ea02018-05-07 20:01:011019 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011020 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:171021 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
1022 EXPECT_EQ("", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011023 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221024 int64_t response_size = reads_size - strlen(junk);
1025 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:171026}
1027
[email protected]0877e3d2009-10-17 22:29:571028// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:011029TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:191030 std::string final_chunk = "0\r\n\r\n";
1031 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1032 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:571033 MockRead data_reads[] = {
1034 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1035 MockRead("5\r\nHello\r\n"),
1036 MockRead("1\r\n"),
1037 MockRead(" \r\n"),
1038 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:191039 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:061040 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:571041 };
Ryan Sleevib8d7ea02018-05-07 20:01:011042 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011043 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:571044 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1045 EXPECT_EQ("Hello world", out.response_data);
Ryan Sleevib8d7ea02018-05-07 20:01:011046 int64_t reads_size = CountReadBytes(data_reads);
sclittlefb249892015-09-10 21:33:221047 int64_t response_size = reads_size - extra_data.size();
1048 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:571049}
1050
[email protected]9fe44f52010-09-23 18:36:001051// Next tests deal with http://crbug.com/56344.
1052
bncd16676a2016-07-20 16:23:011053TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001054 MultipleContentLengthHeadersNoTransferEncoding) {
1055 MockRead data_reads[] = {
1056 MockRead("HTTP/1.1 200 OK\r\n"),
1057 MockRead("Content-Length: 10\r\n"),
1058 MockRead("Content-Length: 5\r\n\r\n"),
1059 };
Ryan Sleevib8d7ea02018-05-07 20:01:011060 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011061 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:001062}
1063
bncd16676a2016-07-20 16:23:011064TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041065 DuplicateContentLengthHeadersNoTransferEncoding) {
1066 MockRead data_reads[] = {
1067 MockRead("HTTP/1.1 200 OK\r\n"),
1068 MockRead("Content-Length: 5\r\n"),
1069 MockRead("Content-Length: 5\r\n\r\n"),
1070 MockRead("Hello"),
1071 };
Ryan Sleevib8d7ea02018-05-07 20:01:011072 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011073 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041074 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1075 EXPECT_EQ("Hello", out.response_data);
1076}
1077
bncd16676a2016-07-20 16:23:011078TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:041079 ComplexContentLengthHeadersNoTransferEncoding) {
1080 // More than 2 dupes.
1081 {
1082 MockRead data_reads[] = {
1083 MockRead("HTTP/1.1 200 OK\r\n"),
1084 MockRead("Content-Length: 5\r\n"),
1085 MockRead("Content-Length: 5\r\n"),
1086 MockRead("Content-Length: 5\r\n\r\n"),
1087 MockRead("Hello"),
1088 };
Ryan Sleevib8d7ea02018-05-07 20:01:011089 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011090 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041091 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1092 EXPECT_EQ("Hello", out.response_data);
1093 }
1094 // HTTP/1.0
1095 {
1096 MockRead data_reads[] = {
1097 MockRead("HTTP/1.0 200 OK\r\n"),
1098 MockRead("Content-Length: 5\r\n"),
1099 MockRead("Content-Length: 5\r\n"),
1100 MockRead("Content-Length: 5\r\n\r\n"),
1101 MockRead("Hello"),
1102 };
Ryan Sleevib8d7ea02018-05-07 20:01:011103 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011104 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:041105 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1106 EXPECT_EQ("Hello", out.response_data);
1107 }
1108 // 2 dupes and one mismatched.
1109 {
1110 MockRead data_reads[] = {
1111 MockRead("HTTP/1.1 200 OK\r\n"),
1112 MockRead("Content-Length: 10\r\n"),
1113 MockRead("Content-Length: 10\r\n"),
1114 MockRead("Content-Length: 5\r\n\r\n"),
1115 };
Ryan Sleevib8d7ea02018-05-07 20:01:011116 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011117 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:041118 }
1119}
1120
bncd16676a2016-07-20 16:23:011121TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:001122 MultipleContentLengthHeadersTransferEncoding) {
1123 MockRead data_reads[] = {
1124 MockRead("HTTP/1.1 200 OK\r\n"),
1125 MockRead("Content-Length: 666\r\n"),
1126 MockRead("Content-Length: 1337\r\n"),
1127 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1128 MockRead("5\r\nHello\r\n"),
1129 MockRead("1\r\n"),
1130 MockRead(" \r\n"),
1131 MockRead("5\r\nworld\r\n"),
1132 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:061133 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:001134 };
Ryan Sleevib8d7ea02018-05-07 20:01:011135 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011136 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:001137 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1138 EXPECT_EQ("Hello world", out.response_data);
1139}
1140
[email protected]1628fe92011-10-04 23:04:551141// Next tests deal with http://crbug.com/98895.
1142
1143// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:011144TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:551145 MockRead data_reads[] = {
1146 MockRead("HTTP/1.1 200 OK\r\n"),
1147 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1148 MockRead("Content-Length: 5\r\n\r\n"),
1149 MockRead("Hello"),
1150 };
Ryan Sleevib8d7ea02018-05-07 20:01:011151 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011152 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:551153 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1154 EXPECT_EQ("Hello", out.response_data);
1155}
1156
[email protected]54a9c6e52012-03-21 20:10:591157// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:011158TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551159 MockRead data_reads[] = {
1160 MockRead("HTTP/1.1 200 OK\r\n"),
1161 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1162 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1163 MockRead("Content-Length: 5\r\n\r\n"),
1164 MockRead("Hello"),
1165 };
Ryan Sleevib8d7ea02018-05-07 20:01:011166 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011167 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:591168 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1169 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:551170}
1171
1172// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:011173TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:551174 MockRead data_reads[] = {
1175 MockRead("HTTP/1.1 200 OK\r\n"),
1176 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1177 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1178 MockRead("Content-Length: 5\r\n\r\n"),
1179 MockRead("Hello"),
1180 };
Ryan Sleevib8d7ea02018-05-07 20:01:011181 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011182 EXPECT_THAT(out.rv,
1183 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:551184}
1185
[email protected]54a9c6e52012-03-21 20:10:591186// Checks that two identical Location headers result in no error.
1187// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:011188TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551189 MockRead data_reads[] = {
1190 MockRead("HTTP/1.1 302 Redirect\r\n"),
1191 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:591192 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:551193 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061194 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551195 };
1196
1197 HttpRequestInfo request;
1198 request.method = "GET";
1199 request.url = GURL("http://redirect.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101200 request.traffic_annotation =
1201 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1628fe92011-10-04 23:04:551202
danakj1fd259a02016-04-16 03:17:091203 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161204 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1628fe92011-10-04 23:04:551205
Ryan Sleevib8d7ea02018-05-07 20:01:011206 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071207 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:551208
[email protected]49639fa2011-12-20 23:22:411209 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:551210
tfarina42834112016-09-22 13:38:201211 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011212 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:551213
robpercival214763f2016-07-01 23:27:011214 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:551215
bnc691fda62016-08-12 00:43:161216 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521217 ASSERT_TRUE(response);
1218 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551219 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1220 std::string url;
1221 EXPECT_TRUE(response->headers->IsRedirect(&url));
1222 EXPECT_EQ("http://good.com/", url);
tbansal2ecbbc72016-10-06 17:15:471223 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]1628fe92011-10-04 23:04:551224}
1225
[email protected]1628fe92011-10-04 23:04:551226// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011227TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551228 MockRead data_reads[] = {
1229 MockRead("HTTP/1.1 302 Redirect\r\n"),
1230 MockRead("Location: http://good.com/\r\n"),
1231 MockRead("Location: http://evil.com/\r\n"),
1232 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061233 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551234 };
Ryan Sleevib8d7ea02018-05-07 20:01:011235 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:011236 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551237}
1238
[email protected]ef0faf2e72009-03-05 23:27:231239// Do a request using the HEAD method. Verify that we don't try to read the
1240// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011241TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421242 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231243 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231244 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101245 request.traffic_annotation =
1246 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ef0faf2e72009-03-05 23:27:231247
danakj1fd259a02016-04-16 03:17:091248 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161249 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:091250 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:161251 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:091252 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1253 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271254
[email protected]ef0faf2e72009-03-05 23:27:231255 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131256 MockWrite("HEAD / HTTP/1.1\r\n"
1257 "Host: www.example.org\r\n"
1258 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231259 };
1260 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231261 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1262 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231263
mmenked39192ee2015-12-09 00:57:231264 // No response body because the test stops reading here.
1265 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231266 };
1267
Ryan Sleevib8d7ea02018-05-07 20:01:011268 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:071269 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231270
[email protected]49639fa2011-12-20 23:22:411271 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231272
tfarina42834112016-09-22 13:38:201273 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011274 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231275
1276 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011277 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231278
bnc691fda62016-08-12 00:43:161279 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521280 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231281
1282 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521283 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231284 EXPECT_EQ(1234, response->headers->GetContentLength());
1285 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471286 EXPECT_TRUE(response->proxy_server.is_direct());
ryansturm49a8cb12016-06-15 16:51:091287 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1288 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231289
1290 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101291 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231292 bool has_server_header = response->headers->EnumerateHeader(
1293 &iter, "Server", &server_header);
1294 EXPECT_TRUE(has_server_header);
1295 EXPECT_EQ("Blah", server_header);
1296
1297 // Reading should give EOF right away, since there is no message body
1298 // (despite non-zero content-length).
1299 std::string response_data;
bnc691fda62016-08-12 00:43:161300 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011301 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231302 EXPECT_EQ("", response_data);
1303}
1304
bncd16676a2016-07-20 16:23:011305TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091306 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521307
1308 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351309 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1310 MockRead("hello"),
1311 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1312 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061313 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521314 };
Ryan Sleevib8d7ea02018-05-07 20:01:011315 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071316 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521317
[email protected]0b0bf032010-09-21 18:08:501318 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521319 "hello", "world"
1320 };
1321
1322 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421323 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521324 request.method = "GET";
bncce36dca22015-04-21 22:11:231325 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:101326 request.traffic_annotation =
1327 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521328
bnc691fda62016-08-12 00:43:161329 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271330
[email protected]49639fa2011-12-20 23:22:411331 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521332
tfarina42834112016-09-22 13:38:201333 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011334 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521335
1336 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011337 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521338
bnc691fda62016-08-12 00:43:161339 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521340 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521341
wezca1070932016-05-26 20:30:521342 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251343 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
tbansal2ecbbc72016-10-06 17:15:471344 EXPECT_TRUE(response->proxy_server.is_direct());
initial.commit586acc5fe2008-07-26 22:42:521345
1346 std::string response_data;
bnc691fda62016-08-12 00:43:161347 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011348 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251349 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521350 }
1351}
1352
bncd16676a2016-07-20 16:23:011353TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091354 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221355 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:191356 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:221357 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271358
[email protected]1c773ea12009-04-28 19:58:421359 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521360 request.method = "POST";
1361 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271362 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:101363 request.traffic_annotation =
1364 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521365
shivanishab9a143952016-09-19 17:23:411366 // Check the upload progress returned before initialization is correct.
1367 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1368 EXPECT_EQ(0u, progress.size());
1369 EXPECT_EQ(0u, progress.position());
1370
danakj1fd259a02016-04-16 03:17:091371 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161372 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271373
initial.commit586acc5fe2008-07-26 22:42:521374 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351375 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1376 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1377 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061378 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521379 };
Ryan Sleevib8d7ea02018-05-07 20:01:011380 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071381 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521382
[email protected]49639fa2011-12-20 23:22:411383 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521384
tfarina42834112016-09-22 13:38:201385 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011386 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521387
1388 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011389 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521390
bnc691fda62016-08-12 00:43:161391 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521392 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521393
wezca1070932016-05-26 20:30:521394 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251395 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521396
1397 std::string response_data;
bnc691fda62016-08-12 00:43:161398 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011399 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251400 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521401}
1402
[email protected]3a2d3662009-03-27 03:49:141403// This test is almost the same as Ignores100 above, but the response contains
1404// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571405// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011406TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421407 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141408 request.method = "GET";
1409 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101410 request.traffic_annotation =
1411 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3a2d3662009-03-27 03:49:141412
danakj1fd259a02016-04-16 03:17:091413 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161414 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271415
[email protected]3a2d3662009-03-27 03:49:141416 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571417 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1418 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141419 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061420 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141421 };
Ryan Sleevib8d7ea02018-05-07 20:01:011422 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071423 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141424
[email protected]49639fa2011-12-20 23:22:411425 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141426
tfarina42834112016-09-22 13:38:201427 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011428 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141429
1430 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011431 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141432
bnc691fda62016-08-12 00:43:161433 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521434 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141435
wezca1070932016-05-26 20:30:521436 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141437 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1438
1439 std::string response_data;
bnc691fda62016-08-12 00:43:161440 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011441 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141442 EXPECT_EQ("hello world", response_data);
1443}
1444
Andrew Comminos517a92c2019-01-14 17:49:561445TEST_F(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1446 static const base::TimeDelta kDelayAfterFirstByte =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381447 base::TimeDelta::FromMilliseconds(10);
1448
1449 HttpRequestInfo request;
1450 request.method = "GET";
1451 request.url = GURL("http://www.foo.com/");
1452 request.traffic_annotation =
1453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1454
1455 std::vector<MockWrite> data_writes = {
1456 MockWrite(ASYNC, 0,
1457 "GET / HTTP/1.1\r\n"
1458 "Host: www.foo.com\r\n"
1459 "Connection: keep-alive\r\n\r\n"),
1460 };
1461
1462 std::vector<MockRead> data_reads = {
1463 // Write one byte of the status line, followed by a pause.
1464 MockRead(ASYNC, 1, "H"),
1465 MockRead(ASYNC, ERR_IO_PENDING, 2),
1466 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1467 MockRead(ASYNC, 4, "hello world"),
1468 MockRead(SYNCHRONOUS, OK, 5),
1469 };
1470
1471 SequencedSocketData data(data_reads, data_writes);
1472 session_deps_.socket_factory->AddSocketDataProvider(&data);
1473
1474 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1475
1476 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1477
1478 TestCompletionCallback callback;
1479
1480 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1481 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1482
1483 data.RunUntilPaused();
1484 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561485 FastForwardBy(kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381486 data.Resume();
1487
1488 rv = callback.WaitForResult();
1489 EXPECT_THAT(rv, IsOk());
1490
1491 const HttpResponseInfo* response = trans.GetResponseInfo();
1492 ASSERT_TRUE(response);
1493
1494 EXPECT_TRUE(response->headers);
1495 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1496
1497 LoadTimingInfo load_timing_info;
1498 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1499 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1500 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561501 // Ensure we didn't include the delay in the TTFB time.
1502 EXPECT_EQ(load_timing_info.receive_headers_start,
1503 load_timing_info.connect_timing.connect_end);
1504 // Ensure that the mock clock advanced at all.
1505 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1506 kDelayAfterFirstByte);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381507
1508 std::string response_data;
1509 rv = ReadTransaction(&trans, &response_data);
1510 EXPECT_THAT(rv, IsOk());
1511 EXPECT_EQ("hello world", response_data);
1512}
1513
1514// Tests that the time-to-first-byte reported in a transaction's load timing
1515// info uses the first response, even if 1XX/informational.
1516void HttpNetworkTransactionTest::Check100ResponseTiming(bool use_spdy) {
Andrew Comminos517a92c2019-01-14 17:49:561517 static const base::TimeDelta kDelayAfter100Response =
Andrew Comminos1f2ff1cc2018-12-14 05:22:381518 base::TimeDelta::FromMilliseconds(10);
1519
1520 HttpRequestInfo request;
1521 request.method = "GET";
1522 request.url = GURL("https://www.foo.com/");
1523 request.traffic_annotation =
1524 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1525
1526 SSLSocketDataProvider ssl(ASYNC, OK);
1527 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1528
1529 std::vector<MockWrite> data_writes;
1530 std::vector<MockRead> data_reads;
1531
1532 spdy::SpdySerializedFrame spdy_req(
1533 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1534
1535 spdy::SpdyHeaderBlock spdy_resp1_headers;
1536 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1537 spdy::SpdySerializedFrame spdy_resp1(
1538 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1539 spdy::SpdySerializedFrame spdy_resp2(
1540 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1541 spdy::SpdySerializedFrame spdy_data(
1542 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1543
1544 if (use_spdy) {
1545 ssl.next_proto = kProtoHTTP2;
1546
1547 data_writes = {CreateMockWrite(spdy_req, 0)};
1548
1549 data_reads = {
1550 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1551 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1552 MockRead(SYNCHRONOUS, OK, 5),
1553 };
1554 } else {
1555 data_writes = {
1556 MockWrite(ASYNC, 0,
1557 "GET / HTTP/1.1\r\n"
1558 "Host: www.foo.com\r\n"
1559 "Connection: keep-alive\r\n\r\n"),
1560 };
1561
1562 data_reads = {
1563 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1564 MockRead(ASYNC, ERR_IO_PENDING, 2),
1565
1566 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1567 MockRead(ASYNC, 4, "hello world"),
1568 MockRead(SYNCHRONOUS, OK, 5),
1569 };
1570 }
1571
1572 SequencedSocketData data(data_reads, data_writes);
1573 session_deps_.socket_factory->AddSocketDataProvider(&data);
1574
1575 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1576
1577 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1578
1579 TestCompletionCallback callback;
1580
1581 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1582 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1583
1584 data.RunUntilPaused();
1585 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1586 // the delay before parsing the 200 response.
1587 ASSERT_TRUE(data.IsPaused());
Andrew Comminos517a92c2019-01-14 17:49:561588 FastForwardBy(kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381589 data.Resume();
1590
1591 rv = callback.WaitForResult();
1592 EXPECT_THAT(rv, IsOk());
1593
1594 const HttpResponseInfo* response = trans.GetResponseInfo();
1595 ASSERT_TRUE(response);
1596
1597 LoadTimingInfo load_timing_info;
1598 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1599 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1600 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
Andrew Comminos517a92c2019-01-14 17:49:561601 // Ensure we didn't include the delay in the TTFB time.
1602 EXPECT_EQ(load_timing_info.receive_headers_start,
1603 load_timing_info.connect_timing.connect_end);
1604 // Ensure that the mock clock advanced at all.
1605 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1606 kDelayAfter100Response);
Andrew Comminos1f2ff1cc2018-12-14 05:22:381607
1608 std::string response_data;
1609 rv = ReadTransaction(&trans, &response_data);
1610 EXPECT_THAT(rv, IsOk());
1611 EXPECT_EQ("hello world", response_data);
1612}
1613
Andrew Comminos517a92c2019-01-14 17:49:561614TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381615 Check100ResponseTiming(false /* use_spdy */);
1616}
1617
Andrew Comminos517a92c2019-01-14 17:49:561618TEST_F(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
Andrew Comminos1f2ff1cc2018-12-14 05:22:381619 Check100ResponseTiming(true /* use_spdy */);
1620}
1621
bncd16676a2016-07-20 16:23:011622TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081623 HttpRequestInfo request;
1624 request.method = "POST";
1625 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101626 request.traffic_annotation =
1627 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
zmo9528c9f42015-08-04 22:12:081628
danakj1fd259a02016-04-16 03:17:091629 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161630 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zmo9528c9f42015-08-04 22:12:081631
1632 MockRead data_reads[] = {
1633 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1634 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381635 };
Ryan Sleevib8d7ea02018-05-07 20:01:011636 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
zmo9528c9f42015-08-04 22:12:081637 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381638
zmo9528c9f42015-08-04 22:12:081639 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381640
tfarina42834112016-09-22 13:38:201641 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011642 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381643
zmo9528c9f42015-08-04 22:12:081644 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011645 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381646
zmo9528c9f42015-08-04 22:12:081647 std::string response_data;
bnc691fda62016-08-12 00:43:161648 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011649 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081650 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381651}
1652
bncd16676a2016-07-20 16:23:011653TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381654 HttpRequestInfo request;
1655 request.method = "POST";
1656 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101657 request.traffic_annotation =
1658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ee9410e72010-01-07 01:42:381659
danakj1fd259a02016-04-16 03:17:091660 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:161661 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:271662
[email protected]ee9410e72010-01-07 01:42:381663 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061664 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381665 };
Ryan Sleevib8d7ea02018-05-07 20:01:011666 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071667 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381668
[email protected]49639fa2011-12-20 23:22:411669 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381670
tfarina42834112016-09-22 13:38:201671 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011672 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381673
1674 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011675 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381676}
1677
[email protected]23e482282013-06-14 16:08:021678void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511679 const MockWrite* write_failure,
1680 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421681 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521682 request.method = "GET";
1683 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101684 request.traffic_annotation =
1685 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
initial.commit586acc5fe2008-07-26 22:42:521686
vishal.b62985ca92015-04-17 08:45:511687 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071688 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091689 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271690
[email protected]202965992011-12-07 23:04:511691 // Written data for successfully sending both requests.
1692 MockWrite data1_writes[] = {
1693 MockWrite("GET / HTTP/1.1\r\n"
1694 "Host: www.foo.com\r\n"
1695 "Connection: keep-alive\r\n\r\n"),
1696 MockWrite("GET / HTTP/1.1\r\n"
1697 "Host: www.foo.com\r\n"
1698 "Connection: keep-alive\r\n\r\n")
1699 };
1700
1701 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521702 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351703 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1704 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061705 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521706 };
[email protected]202965992011-12-07 23:04:511707
1708 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491709 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511710 data1_writes[1] = *write_failure;
1711 } else {
1712 ASSERT_TRUE(read_failure);
1713 data1_reads[2] = *read_failure;
1714 }
1715
Ryan Sleevib8d7ea02018-05-07 20:01:011716 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]bb88e1d32013-05-03 23:11:071717 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521718
1719 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351720 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1721 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061722 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521723 };
Ryan Sleevib8d7ea02018-05-07 20:01:011724 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:071725 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521726
thestig9d3bb0c2015-01-24 00:49:511727 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521728 "hello", "world"
1729 };
1730
mikecironef22f9812016-10-04 03:40:191731 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521732 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411733 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521734
bnc691fda62016-08-12 00:43:161735 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
initial.commit586acc5fe2008-07-26 22:42:521736
tfarina42834112016-09-22 13:38:201737 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011738 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521739
1740 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011741 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521742
[email protected]58e32bb2013-01-21 18:23:251743 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161744 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:251745 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1746 if (i == 0) {
1747 first_socket_log_id = load_timing_info.socket_log_id;
1748 } else {
1749 // The second request should be using a new socket.
1750 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1751 }
1752
bnc691fda62016-08-12 00:43:161753 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521754 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521755
wezca1070932016-05-26 20:30:521756 EXPECT_TRUE(response->headers);
tbansal2ecbbc72016-10-06 17:15:471757 EXPECT_TRUE(response->proxy_server.is_direct());
[email protected]3d2a59b2008-09-26 19:44:251758 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521759
1760 std::string response_data;
bnc691fda62016-08-12 00:43:161761 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011762 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251763 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521764 }
1765}
[email protected]3d2a59b2008-09-26 19:44:251766
[email protected]a34f61ee2014-03-18 20:59:491767void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1768 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101769 const MockRead* read_failure,
1770 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491771 HttpRequestInfo request;
1772 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101773 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101774 request.traffic_annotation =
1775 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a34f61ee2014-03-18 20:59:491776
vishal.b62985ca92015-04-17 08:45:511777 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491778 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091779 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491780
[email protected]09356c652014-03-25 15:36:101781 SSLSocketDataProvider ssl1(ASYNC, OK);
1782 SSLSocketDataProvider ssl2(ASYNC, OK);
1783 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361784 ssl1.next_proto = kProtoHTTP2;
1785 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101786 }
1787 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491789
[email protected]09356c652014-03-25 15:36:101790 // SPDY versions of the request and response.
Ryan Hamilton0239aac2018-05-19 00:03:131791 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491792 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131793 spdy::SpdySerializedFrame spdy_response(
Raul Tambre94493c652019-03-11 17:18:351794 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131795 spdy::SpdySerializedFrame spdy_data(
Bence Békyd74f4382018-02-20 18:26:191796 spdy_util_.ConstructSpdyDataFrame(1, "hello", true));
[email protected]a34f61ee2014-03-18 20:59:491797
[email protected]09356c652014-03-25 15:36:101798 // HTTP/1.1 versions of the request and response.
1799 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1800 "Host: www.foo.com\r\n"
1801 "Connection: keep-alive\r\n\r\n";
1802 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1803 const char kHttpData[] = "hello";
1804
1805 std::vector<MockRead> data1_reads;
1806 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491807 if (write_failure) {
1808 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101809 data1_writes.push_back(*write_failure);
1810 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491811 } else {
1812 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101813 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411814 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101815 } else {
1816 data1_writes.push_back(MockWrite(kHttpRequest));
1817 }
1818 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491819 }
1820
Ryan Sleevib8d7ea02018-05-07 20:01:011821 StaticSocketDataProvider data1(data1_reads, data1_writes);
[email protected]a34f61ee2014-03-18 20:59:491822 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1823
[email protected]09356c652014-03-25 15:36:101824 std::vector<MockRead> data2_reads;
1825 std::vector<MockWrite> data2_writes;
1826
1827 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411828 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101829
bncdf80d44fd2016-07-15 20:27:411830 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1831 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101832 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1833 } else {
1834 data2_writes.push_back(
1835 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1836
1837 data2_reads.push_back(
1838 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1839 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1840 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1841 }
Ryan Sleevib8d7ea02018-05-07 20:01:011842 SequencedSocketData data2(data2_reads, data2_writes);
[email protected]a34f61ee2014-03-18 20:59:491843 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1844
1845 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591846 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491847 // Wait for the preconnect to complete.
1848 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1849 base::RunLoop().RunUntilIdle();
Matt Menke9d5e2c92019-02-05 01:42:231850 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491851
1852 // Make the request.
1853 TestCompletionCallback callback;
1854
bnc691fda62016-08-12 00:43:161855 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a34f61ee2014-03-18 20:59:491856
tfarina42834112016-09-22 13:38:201857 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:011858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491859
1860 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011861 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491862
1863 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:161864 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101865 TestLoadTimingNotReused(
1866 load_timing_info,
1867 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491868
bnc691fda62016-08-12 00:43:161869 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:521870 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491871
wezca1070932016-05-26 20:30:521872 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021873 if (response->was_fetched_via_spdy) {
1874 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1875 } else {
1876 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1877 }
[email protected]a34f61ee2014-03-18 20:59:491878
1879 std::string response_data;
bnc691fda62016-08-12 00:43:161880 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:011881 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101882 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491883}
1884
Biljith Jayan45a41722017-08-16 18:43:141885// Test that we do not retry indefinitely when a server sends an error like
Bence Békyd0d69502019-06-25 19:47:181886// ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
Biljith Jayan45a41722017-08-16 18:43:141887// ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
1888TEST_F(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
1889 HttpRequestInfo request;
1890 request.method = "GET";
1891 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101892 request.traffic_annotation =
1893 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141894
1895 // Check whether we give up after the third try.
1896
1897 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131898 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141899 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131900 spdy::SpdySerializedFrame spdy_response_go_away(
1901 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011902 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1903 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141904
1905 // Three go away responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011906 StaticSocketDataProvider data1(data_read1, data_write);
1907 StaticSocketDataProvider data2(data_read1, data_write);
1908 StaticSocketDataProvider data3(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141909
1910 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1911 AddSSLSocketData();
1912 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1913 AddSSLSocketData();
1914 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1915 AddSSLSocketData();
1916
1917 TestCompletionCallback callback;
1918 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1919 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1920
1921 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1922 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1923
1924 rv = callback.WaitForResult();
Bence Békyd0d69502019-06-25 19:47:181925 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
Biljith Jayan45a41722017-08-16 18:43:141926}
1927
1928TEST_F(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
1929 HttpRequestInfo request;
1930 request.method = "GET";
1931 request.url = GURL("https://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:101932 request.traffic_annotation =
1933 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Biljith Jayan45a41722017-08-16 18:43:141934
1935 // Check whether we try atleast thrice before giving up.
1936
1937 // Construct an HTTP2 request and a "Go away" response.
Ryan Hamilton0239aac2018-05-19 00:03:131938 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
Biljith Jayan45a41722017-08-16 18:43:141939 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
Ryan Hamilton0239aac2018-05-19 00:03:131940 spdy::SpdySerializedFrame spdy_response_go_away(
1941 spdy_util_.ConstructSpdyGoAway(0));
Ryan Sleevib8d7ea02018-05-07 20:01:011942 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
1943 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
Biljith Jayan45a41722017-08-16 18:43:141944
1945 // Construct a non error HTTP2 response.
Ryan Hamilton0239aac2018-05-19 00:03:131946 spdy::SpdySerializedFrame spdy_response_no_error(
Biljith Jayan45a41722017-08-16 18:43:141947 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:131948 spdy::SpdySerializedFrame spdy_data(
1949 spdy_util_.ConstructSpdyDataFrame(1, true));
Biljith Jayan45a41722017-08-16 18:43:141950 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
1951 CreateMockRead(spdy_data, 2)};
1952
1953 // Two error responses.
Ryan Sleevib8d7ea02018-05-07 20:01:011954 StaticSocketDataProvider data1(data_read1, data_write);
1955 StaticSocketDataProvider data2(data_read1, data_write);
Biljith Jayan45a41722017-08-16 18:43:141956 // Followed by a success response.
Ryan Sleevib8d7ea02018-05-07 20:01:011957 SequencedSocketData data3(data_read2, data_write);
Biljith Jayan45a41722017-08-16 18:43:141958
1959 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1960 AddSSLSocketData();
1961 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1962 AddSSLSocketData();
1963 session_deps_.socket_factory->AddSocketDataProvider(&data3);
1964 AddSSLSocketData();
1965
1966 TestCompletionCallback callback;
1967 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1968 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1969
1970 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1971 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1972
1973 rv = callback.WaitForResult();
1974 EXPECT_THAT(rv, IsOk());
1975}
1976
bncd16676a2016-07-20 16:23:011977TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061978 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:351979 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
[email protected]202965992011-12-07 23:04:511980}
1981
bncd16676a2016-07-20 16:23:011982TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061983 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:351984 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251985}
1986
bncd16676a2016-07-20 16:23:011987TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061988 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:351989 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251990}
1991
[email protected]d58ceea82014-06-04 10:55:541992// Make sure that on a 408 response (Request Timeout), the request is retried,
1993// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011994TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541995 MockRead read_failure(SYNCHRONOUS,
1996 "HTTP/1.1 408 Request Timeout\r\n"
1997 "Connection: Keep-Alive\r\n"
1998 "Content-Length: 6\r\n\r\n"
1999 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352000 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
[email protected]d58ceea82014-06-04 10:55:542001}
2002
bncd16676a2016-07-20 16:23:012003TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:492004 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352005 PreconnectErrorResendRequestTest(&write_failure, nullptr, false);
[email protected]a34f61ee2014-03-18 20:59:492006}
2007
bncd16676a2016-07-20 16:23:012008TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:492009 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352010 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:492011}
2012
bncd16676a2016-07-20 16:23:012013TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:492014 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352015 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:102016}
2017
bncd16676a2016-07-20 16:23:012018TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102019 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352020 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]09356c652014-03-25 15:36:102021}
2022
[email protected]d58ceea82014-06-04 10:55:542023// Make sure that on a 408 response (Request Timeout), the request is retried,
2024// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:012025TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:542026 MockRead read_failure(SYNCHRONOUS,
2027 "HTTP/1.1 408 Request Timeout\r\n"
2028 "Connection: Keep-Alive\r\n"
2029 "Content-Length: 6\r\n\r\n"
2030 "Pickle");
Raul Tambre94493c652019-03-11 17:18:352031 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2032 PreconnectErrorResendRequestTest(nullptr, &read_failure, false);
[email protected]d58ceea82014-06-04 10:55:542033}
2034
bncd16676a2016-07-20 16:23:012035TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:102036 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
Raul Tambre94493c652019-03-11 17:18:352037 PreconnectErrorResendRequestTest(&write_failure, nullptr, true);
[email protected]09356c652014-03-25 15:36:102038}
2039
bncd16676a2016-07-20 16:23:012040TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:102041 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
Raul Tambre94493c652019-03-11 17:18:352042 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102043}
2044
bncd16676a2016-07-20 16:23:012045TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:102046 MockRead read_failure(SYNCHRONOUS, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352047 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]09356c652014-03-25 15:36:102048}
2049
bncd16676a2016-07-20 16:23:012050TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:102051 MockRead read_failure(ASYNC, OK); // EOF
Raul Tambre94493c652019-03-11 17:18:352052 PreconnectErrorResendRequestTest(nullptr, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:492053}
2054
bncd16676a2016-07-20 16:23:012055TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:422056 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:252057 request.method = "GET";
bncce36dca22015-04-21 22:11:232058 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102059 request.traffic_annotation =
2060 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3d2a59b2008-09-26 19:44:252061
danakj1fd259a02016-04-16 03:17:092062 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162063 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272064
[email protected]3d2a59b2008-09-26 19:44:252065 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062066 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:352067 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2068 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062069 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252070 };
Ryan Sleevib8d7ea02018-05-07 20:01:012071 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072072 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:252073
[email protected]49639fa2011-12-20 23:22:412074 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:252075
tfarina42834112016-09-22 13:38:202076 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:252078
2079 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012080 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:592081
2082 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162083 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592084 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:252085}
2086
2087// What do various browsers do when the server closes a non-keepalive
2088// connection without sending any response header or body?
2089//
2090// IE7: error page
2091// Safari 3.1.2 (Windows): error page
2092// Firefox 3.0.1: blank page
2093// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:422094// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2095// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:012096TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:252097 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062098 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:352099 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2100 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:062101 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:252102 };
Ryan Sleevib8d7ea02018-05-07 20:01:012103 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
robpercival214763f2016-07-01 23:27:012104 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:252105}
[email protected]1826a402014-01-08 15:40:482106
[email protected]7a5378b2012-11-04 03:25:172107// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2108// tests. There was a bug causing HttpNetworkTransaction to hang in the
2109// destructor in such situations.
2110// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:012111TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:172112 HttpRequestInfo request;
2113 request.method = "GET";
bncce36dca22015-04-21 22:11:232114 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102115 request.traffic_annotation =
2116 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172117
danakj1fd259a02016-04-16 03:17:092118 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582119 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192120 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172121
2122 MockRead data_reads[] = {
2123 MockRead("HTTP/1.0 200 OK\r\n"),
2124 MockRead("Connection: keep-alive\r\n"),
2125 MockRead("Content-Length: 100\r\n\r\n"),
2126 MockRead("hello"),
2127 MockRead(SYNCHRONOUS, 0),
2128 };
Ryan Sleevib8d7ea02018-05-07 20:01:012129 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072130 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172131
2132 TestCompletionCallback callback;
2133
tfarina42834112016-09-22 13:38:202134 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012135 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172136
2137 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012138 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172139
Victor Costan9c7302b2018-08-27 16:39:442140 scoped_refptr<IOBufferWithSize> io_buf =
2141 base::MakeRefCounted<IOBufferWithSize>(100);
[email protected]90499482013-06-01 00:39:502142 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172143 if (rv == ERR_IO_PENDING)
2144 rv = callback.WaitForResult();
2145 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:502146 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:012147 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172148
2149 trans.reset();
fdoray92e35a72016-06-10 15:54:552150 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172151 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2152}
2153
bncd16676a2016-07-20 16:23:012154TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:172155 HttpRequestInfo request;
2156 request.method = "GET";
bncce36dca22015-04-21 22:11:232157 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102158 request.traffic_annotation =
2159 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7a5378b2012-11-04 03:25:172160
danakj1fd259a02016-04-16 03:17:092161 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:582162 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192163 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7a5378b2012-11-04 03:25:172164
2165 MockRead data_reads[] = {
2166 MockRead("HTTP/1.0 200 OK\r\n"),
2167 MockRead("Connection: keep-alive\r\n"),
2168 MockRead("Content-Length: 100\r\n\r\n"),
2169 MockRead(SYNCHRONOUS, 0),
2170 };
Ryan Sleevib8d7ea02018-05-07 20:01:012171 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:072172 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:172173
2174 TestCompletionCallback callback;
2175
tfarina42834112016-09-22 13:38:202176 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012177 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:172178
2179 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012180 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:172181
Victor Costan9c7302b2018-08-27 16:39:442182 scoped_refptr<IOBufferWithSize> io_buf(
2183 base::MakeRefCounted<IOBufferWithSize>(100));
[email protected]90499482013-06-01 00:39:502184 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:172185 if (rv == ERR_IO_PENDING)
2186 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:012187 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:172188
2189 trans.reset();
fdoray92e35a72016-06-10 15:54:552190 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:172191 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2192}
2193
[email protected]0b0bf032010-09-21 18:08:502194// Test that we correctly reuse a keep-alive connection after not explicitly
2195// reading the body.
bncd16676a2016-07-20 16:23:012196TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:132197 HttpRequestInfo request;
2198 request.method = "GET";
2199 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102200 request.traffic_annotation =
2201 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]fc31d6a42010-06-24 18:05:132202
vishal.b62985ca92015-04-17 08:45:512203 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:072204 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:092205 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272206
mmenkecc2298e2015-12-07 18:20:182207 const char* request_data =
2208 "GET / HTTP/1.1\r\n"
2209 "Host: www.foo.com\r\n"
2210 "Connection: keep-alive\r\n\r\n";
2211 MockWrite data_writes[] = {
2212 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
2213 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
2214 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
2215 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
2216 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
2217 };
2218
[email protected]0b0bf032010-09-21 18:08:502219 // Note that because all these reads happen in the same
2220 // StaticSocketDataProvider, it shows that the same socket is being reused for
2221 // all transactions.
mmenkecc2298e2015-12-07 18:20:182222 MockRead data_reads[] = {
2223 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2224 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2225 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2226 MockRead(ASYNC, 7,
2227 "HTTP/1.1 302 Found\r\n"
2228 "Content-Length: 0\r\n\r\n"),
2229 MockRead(ASYNC, 9,
2230 "HTTP/1.1 302 Found\r\n"
2231 "Content-Length: 5\r\n\r\n"
2232 "hello"),
2233 MockRead(ASYNC, 11,
2234 "HTTP/1.1 301 Moved Permanently\r\n"
2235 "Content-Length: 0\r\n\r\n"),
2236 MockRead(ASYNC, 13,
2237 "HTTP/1.1 301 Moved Permanently\r\n"
2238 "Content-Length: 5\r\n\r\n"
2239 "hello"),
[email protected]fc31d6a42010-06-24 18:05:132240
mmenkecc2298e2015-12-07 18:20:182241 // In the next two rounds, IsConnectedAndIdle returns false, due to
2242 // the set_busy_before_sync_reads(true) call, while the
2243 // HttpNetworkTransaction is being shut down, but the socket is still
2244 // reuseable. See http://crbug.com/544255.
2245 MockRead(ASYNC, 15,
2246 "HTTP/1.1 200 Hunky-Dory\r\n"
2247 "Content-Length: 5\r\n\r\n"),
2248 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:132249
mmenkecc2298e2015-12-07 18:20:182250 MockRead(ASYNC, 18,
2251 "HTTP/1.1 200 Hunky-Dory\r\n"
2252 "Content-Length: 5\r\n\r\n"
2253 "he"),
2254 MockRead(SYNCHRONOUS, 19, "llo"),
2255
2256 // The body of the final request is actually read.
2257 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2258 MockRead(ASYNC, 22, "hello"),
2259 };
Ryan Sleevib8d7ea02018-05-07 20:01:012260 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:182261 data.set_busy_before_sync_reads(true);
2262 session_deps_.socket_factory->AddSocketDataProvider(&data);
2263
Avi Drissman4365a4782018-12-28 19:26:242264 const int kNumUnreadBodies = base::size(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:502265 std::string response_lines[kNumUnreadBodies];
2266
mikecironef22f9812016-10-04 03:40:192267 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
mmenkecc2298e2015-12-07 18:20:182268 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:412269 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:132270
Jeremy Roman0579ed62017-08-29 15:56:192271 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
bnc87dcefc2017-05-25 12:47:582272 session.get());
[email protected]fc31d6a42010-06-24 18:05:132273
tfarina42834112016-09-22 13:38:202274 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012275 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:132276
[email protected]58e32bb2013-01-21 18:23:252277 LoadTimingInfo load_timing_info;
2278 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2279 if (i == 0) {
2280 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2281 first_socket_log_id = load_timing_info.socket_log_id;
2282 } else {
2283 TestLoadTimingReused(load_timing_info);
2284 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2285 }
2286
[email protected]fc31d6a42010-06-24 18:05:132287 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182288 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:132289
mmenkecc2298e2015-12-07 18:20:182290 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502291 response_lines[i] = response->headers->GetStatusLine();
2292
mmenkecc2298e2015-12-07 18:20:182293 // Delete the transaction without reading the response bodies. Then spin
2294 // the message loop, so the response bodies are drained.
2295 trans.reset();
2296 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:132297 }
[email protected]0b0bf032010-09-21 18:08:502298
2299 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:182300 "HTTP/1.1 204 No Content",
2301 "HTTP/1.1 205 Reset Content",
2302 "HTTP/1.1 304 Not Modified",
2303 "HTTP/1.1 302 Found",
2304 "HTTP/1.1 302 Found",
2305 "HTTP/1.1 301 Moved Permanently",
2306 "HTTP/1.1 301 Moved Permanently",
2307 "HTTP/1.1 200 Hunky-Dory",
2308 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:502309 };
2310
Avi Drissman4365a4782018-12-28 19:26:242311 static_assert(kNumUnreadBodies == base::size(kStatusLines),
mostynb91e0da982015-01-20 19:17:272312 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:502313
2314 for (int i = 0; i < kNumUnreadBodies; ++i)
2315 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2316
[email protected]49639fa2011-12-20 23:22:412317 TestCompletionCallback callback;
bnc691fda62016-08-12 00:43:162318 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202319 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012320 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:162321 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:182322 ASSERT_TRUE(response);
2323 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:502324 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2325 std::string response_data;
bnc691fda62016-08-12 00:43:162326 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:012327 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:502328 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:132329}
2330
mmenke5f94fda2016-06-02 20:54:132331// Sockets that receive extra data after a response is complete should not be
2332// reused.
bncd16676a2016-07-20 16:23:012333TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:132334 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2335 MockWrite data_writes1[] = {
2336 MockWrite("HEAD / HTTP/1.1\r\n"
2337 "Host: www.borked.com\r\n"
2338 "Connection: keep-alive\r\n\r\n"),
2339 };
2340
2341 MockRead data_reads1[] = {
2342 MockRead("HTTP/1.1 200 OK\r\n"
2343 "Connection: keep-alive\r\n"
2344 "Content-Length: 22\r\n\r\n"
2345 "This server is borked."),
2346 };
2347
2348 MockWrite data_writes2[] = {
2349 MockWrite("GET /foo HTTP/1.1\r\n"
2350 "Host: www.borked.com\r\n"
2351 "Connection: keep-alive\r\n\r\n"),
2352 };
2353
2354 MockRead data_reads2[] = {
2355 MockRead("HTTP/1.1 200 OK\r\n"
2356 "Content-Length: 3\r\n\r\n"
2357 "foo"),
2358 };
Ryan Sleevib8d7ea02018-05-07 20:01:012359 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132360 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012361 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132362 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2363
2364 TestCompletionCallback callback;
2365 HttpRequestInfo request1;
2366 request1.method = "HEAD";
2367 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102368 request1.traffic_annotation =
2369 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132370
bnc87dcefc2017-05-25 12:47:582371 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192372 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202373 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012374 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132375
2376 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2377 ASSERT_TRUE(response1);
2378 ASSERT_TRUE(response1->headers);
2379 EXPECT_EQ(200, response1->headers->response_code());
2380 EXPECT_TRUE(response1->headers->IsKeepAlive());
2381
2382 std::string response_data1;
robpercival214763f2016-07-01 23:27:012383 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132384 EXPECT_EQ("", response_data1);
2385 // Deleting the transaction attempts to release the socket back into the
2386 // socket pool.
2387 trans1.reset();
2388
2389 HttpRequestInfo request2;
2390 request2.method = "GET";
2391 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102392 request2.traffic_annotation =
2393 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132394
bnc87dcefc2017-05-25 12:47:582395 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192396 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202397 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012398 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132399
2400 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2401 ASSERT_TRUE(response2);
2402 ASSERT_TRUE(response2->headers);
2403 EXPECT_EQ(200, response2->headers->response_code());
2404
2405 std::string response_data2;
robpercival214763f2016-07-01 23:27:012406 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132407 EXPECT_EQ("foo", response_data2);
2408}
2409
bncd16676a2016-07-20 16:23:012410TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:132411 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2412 MockWrite data_writes1[] = {
2413 MockWrite("GET / HTTP/1.1\r\n"
2414 "Host: www.borked.com\r\n"
2415 "Connection: keep-alive\r\n\r\n"),
2416 };
2417
2418 MockRead data_reads1[] = {
2419 MockRead("HTTP/1.1 200 OK\r\n"
2420 "Connection: keep-alive\r\n"
2421 "Content-Length: 22\r\n\r\n"
2422 "This server is borked."
2423 "Bonus data!"),
2424 };
2425
2426 MockWrite data_writes2[] = {
2427 MockWrite("GET /foo HTTP/1.1\r\n"
2428 "Host: www.borked.com\r\n"
2429 "Connection: keep-alive\r\n\r\n"),
2430 };
2431
2432 MockRead data_reads2[] = {
2433 MockRead("HTTP/1.1 200 OK\r\n"
2434 "Content-Length: 3\r\n\r\n"
2435 "foo"),
2436 };
Ryan Sleevib8d7ea02018-05-07 20:01:012437 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132438 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012439 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132440 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2441
2442 TestCompletionCallback callback;
2443 HttpRequestInfo request1;
2444 request1.method = "GET";
2445 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102446 request1.traffic_annotation =
2447 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132448
bnc87dcefc2017-05-25 12:47:582449 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192450 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202451 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012452 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132453
2454 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2455 ASSERT_TRUE(response1);
2456 ASSERT_TRUE(response1->headers);
2457 EXPECT_EQ(200, response1->headers->response_code());
2458 EXPECT_TRUE(response1->headers->IsKeepAlive());
2459
2460 std::string response_data1;
robpercival214763f2016-07-01 23:27:012461 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132462 EXPECT_EQ("This server is borked.", response_data1);
2463 // Deleting the transaction attempts to release the socket back into the
2464 // socket pool.
2465 trans1.reset();
2466
2467 HttpRequestInfo request2;
2468 request2.method = "GET";
2469 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102470 request2.traffic_annotation =
2471 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132472
bnc87dcefc2017-05-25 12:47:582473 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192474 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202475 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012476 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132477
2478 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2479 ASSERT_TRUE(response2);
2480 ASSERT_TRUE(response2->headers);
2481 EXPECT_EQ(200, response2->headers->response_code());
2482
2483 std::string response_data2;
robpercival214763f2016-07-01 23:27:012484 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132485 EXPECT_EQ("foo", response_data2);
2486}
2487
bncd16676a2016-07-20 16:23:012488TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:132489 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2490 MockWrite data_writes1[] = {
2491 MockWrite("GET / HTTP/1.1\r\n"
2492 "Host: www.borked.com\r\n"
2493 "Connection: keep-alive\r\n\r\n"),
2494 };
2495
2496 MockRead data_reads1[] = {
2497 MockRead("HTTP/1.1 200 OK\r\n"
2498 "Connection: keep-alive\r\n"
2499 "Transfer-Encoding: chunked\r\n\r\n"),
2500 MockRead("16\r\nThis server is borked.\r\n"),
2501 MockRead("0\r\n\r\nBonus data!"),
2502 };
2503
2504 MockWrite data_writes2[] = {
2505 MockWrite("GET /foo HTTP/1.1\r\n"
2506 "Host: www.borked.com\r\n"
2507 "Connection: keep-alive\r\n\r\n"),
2508 };
2509
2510 MockRead data_reads2[] = {
2511 MockRead("HTTP/1.1 200 OK\r\n"
2512 "Content-Length: 3\r\n\r\n"
2513 "foo"),
2514 };
Ryan Sleevib8d7ea02018-05-07 20:01:012515 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132516 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:012517 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke5f94fda2016-06-02 20:54:132518 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2519
2520 TestCompletionCallback callback;
2521 HttpRequestInfo request1;
2522 request1.method = "GET";
2523 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102524 request1.traffic_annotation =
2525 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132526
bnc87dcefc2017-05-25 12:47:582527 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:192528 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202529 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012530 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132531
2532 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2533 ASSERT_TRUE(response1);
2534 ASSERT_TRUE(response1->headers);
2535 EXPECT_EQ(200, response1->headers->response_code());
2536 EXPECT_TRUE(response1->headers->IsKeepAlive());
2537
2538 std::string response_data1;
robpercival214763f2016-07-01 23:27:012539 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132540 EXPECT_EQ("This server is borked.", response_data1);
2541 // Deleting the transaction attempts to release the socket back into the
2542 // socket pool.
2543 trans1.reset();
2544
2545 HttpRequestInfo request2;
2546 request2.method = "GET";
2547 request2.url = GURL("http://www.borked.com/foo");
Ramin Halavatib5e433e62018-02-07 07:41:102548 request2.traffic_annotation =
2549 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132550
bnc87dcefc2017-05-25 12:47:582551 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:192552 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:202553 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012554 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132555
2556 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2557 ASSERT_TRUE(response2);
2558 ASSERT_TRUE(response2->headers);
2559 EXPECT_EQ(200, response2->headers->response_code());
2560
2561 std::string response_data2;
robpercival214763f2016-07-01 23:27:012562 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132563 EXPECT_EQ("foo", response_data2);
2564}
2565
2566// This is a little different from the others - it tests the case that the
2567// HttpStreamParser doesn't know if there's extra data on a socket or not when
2568// the HttpNetworkTransaction is torn down, because the response body hasn't
2569// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012570TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132571 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2572 MockWrite data_writes1[] = {
2573 MockWrite("GET / HTTP/1.1\r\n"
2574 "Host: www.borked.com\r\n"
2575 "Connection: keep-alive\r\n\r\n"),
2576 };
2577
2578 MockRead data_reads1[] = {
2579 MockRead("HTTP/1.1 200 OK\r\n"
2580 "Connection: keep-alive\r\n"
2581 "Transfer-Encoding: chunked\r\n\r\n"),
2582 MockRead("16\r\nThis server is borked.\r\n"),
2583 MockRead("0\r\n\r\nBonus data!"),
2584 };
Ryan Sleevib8d7ea02018-05-07 20:01:012585 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke5f94fda2016-06-02 20:54:132586 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2587
2588 TestCompletionCallback callback;
2589 HttpRequestInfo request1;
2590 request1.method = "GET";
2591 request1.url = GURL("http://www.borked.com/");
Ramin Halavatib5e433e62018-02-07 07:41:102592 request1.traffic_annotation =
2593 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke5f94fda2016-06-02 20:54:132594
bnc87dcefc2017-05-25 12:47:582595 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:192596 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
bnc87dcefc2017-05-25 12:47:582597 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012598 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132599
bnc87dcefc2017-05-25 12:47:582600 const HttpResponseInfo* response1 = trans->GetResponseInfo();
mmenke5f94fda2016-06-02 20:54:132601 ASSERT_TRUE(response1);
2602 ASSERT_TRUE(response1->headers);
2603 EXPECT_EQ(200, response1->headers->response_code());
2604 EXPECT_TRUE(response1->headers->IsKeepAlive());
2605
2606 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2607 // response body.
bnc87dcefc2017-05-25 12:47:582608 trans.reset();
mmenke5f94fda2016-06-02 20:54:132609
2610 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2611 // socket can't be reused, rather than returning it to the socket pool.
2612 base::RunLoop().RunUntilIdle();
2613
2614 // There should be no idle sockets in the pool.
2615 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2616}
2617
[email protected]038e9a32008-10-08 22:40:162618// Test the request-challenge-retry sequence for basic auth.
2619// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012620TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422621 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162622 request.method = "GET";
bncce36dca22015-04-21 22:11:232623 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102624 request.traffic_annotation =
2625 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]038e9a32008-10-08 22:40:162626
vishal.b62985ca92015-04-17 08:45:512627 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072628 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092629 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162630 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272631
[email protected]f9ee6b52008-11-08 06:46:232632 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232633 MockWrite(
2634 "GET / HTTP/1.1\r\n"
2635 "Host: www.example.org\r\n"
2636 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232637 };
2638
[email protected]038e9a32008-10-08 22:40:162639 MockRead data_reads1[] = {
2640 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2641 // Give a couple authenticate options (only the middle one is actually
2642 // supported).
[email protected]22927ad2009-09-21 19:56:192643 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162644 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2645 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2646 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2647 // Large content-length -- won't matter, as connection will be reset.
2648 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062649 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162650 };
2651
2652 // After calling trans->RestartWithAuth(), this is the request we should
2653 // be issuing -- the final header line contains the credentials.
2654 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232655 MockWrite(
2656 "GET / HTTP/1.1\r\n"
2657 "Host: www.example.org\r\n"
2658 "Connection: keep-alive\r\n"
2659 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162660 };
2661
2662 // Lastly, the server responds with the actual content.
2663 MockRead data_reads2[] = {
2664 MockRead("HTTP/1.0 200 OK\r\n"),
2665 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2666 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062667 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162668 };
2669
Ryan Sleevib8d7ea02018-05-07 20:01:012670 StaticSocketDataProvider data1(data_reads1, data_writes1);
2671 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:072672 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2673 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162674
[email protected]49639fa2011-12-20 23:22:412675 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162676
tfarina42834112016-09-22 13:38:202677 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012678 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162679
2680 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012681 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162682
[email protected]58e32bb2013-01-21 18:23:252683 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162684 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
[email protected]58e32bb2013-01-21 18:23:252685 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2686
Ryan Sleevib8d7ea02018-05-07 20:01:012687 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162688 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012689 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162690 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192691
bnc691fda62016-08-12 00:43:162692 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522693 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582694 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:162695
[email protected]49639fa2011-12-20 23:22:412696 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162697
bnc691fda62016-08-12 00:43:162698 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012699 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162700
2701 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012702 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162703
[email protected]58e32bb2013-01-21 18:23:252704 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162705 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
[email protected]58e32bb2013-01-21 18:23:252706 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2707 // The load timing after restart should have a new socket ID, and times after
2708 // those of the first load timing.
2709 EXPECT_LE(load_timing_info1.receive_headers_end,
2710 load_timing_info2.connect_timing.connect_start);
2711 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2712
Ryan Sleevib8d7ea02018-05-07 20:01:012713 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162714 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012715 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162716 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192717
bnc691fda62016-08-12 00:43:162718 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522719 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582720 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:162721 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162722}
2723
ttuttled9dbc652015-09-29 20:00:592724// Test the request-challenge-retry sequence for basic auth.
2725// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012726TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592727 HttpRequestInfo request;
2728 request.method = "GET";
2729 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102730 request.traffic_annotation =
2731 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttled9dbc652015-09-29 20:00:592732
2733 TestNetLog log;
2734 MockHostResolver* resolver = new MockHostResolver();
2735 session_deps_.net_log = &log;
2736 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092737 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
bnc691fda62016-08-12 00:43:162738 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttled9dbc652015-09-29 20:00:592739
2740 resolver->rules()->ClearRules();
2741 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2742
2743 MockWrite data_writes1[] = {
2744 MockWrite("GET / HTTP/1.1\r\n"
2745 "Host: www.example.org\r\n"
2746 "Connection: keep-alive\r\n\r\n"),
2747 };
2748
2749 MockRead data_reads1[] = {
2750 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2751 // Give a couple authenticate options (only the middle one is actually
2752 // supported).
2753 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2755 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2756 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2757 // Large content-length -- won't matter, as connection will be reset.
2758 MockRead("Content-Length: 10000\r\n\r\n"),
2759 MockRead(SYNCHRONOUS, ERR_FAILED),
2760 };
2761
2762 // After calling trans->RestartWithAuth(), this is the request we should
2763 // be issuing -- the final header line contains the credentials.
2764 MockWrite data_writes2[] = {
2765 MockWrite("GET / HTTP/1.1\r\n"
2766 "Host: www.example.org\r\n"
2767 "Connection: keep-alive\r\n"
2768 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2769 };
2770
2771 // Lastly, the server responds with the actual content.
2772 MockRead data_reads2[] = {
2773 MockRead("HTTP/1.0 200 OK\r\n"),
2774 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2775 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2776 };
2777
Ryan Sleevib8d7ea02018-05-07 20:01:012778 StaticSocketDataProvider data1(data_reads1, data_writes1);
2779 StaticSocketDataProvider data2(data_reads2, data_writes2);
ttuttled9dbc652015-09-29 20:00:592780 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2781 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2782
2783 TestCompletionCallback callback1;
2784
bnc691fda62016-08-12 00:43:162785 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
tfarina42834112016-09-22 13:38:202786 NetLogWithSource())));
ttuttled9dbc652015-09-29 20:00:592787
2788 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:162789 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
ttuttled9dbc652015-09-29 20:00:592790 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2791
Ryan Sleevib8d7ea02018-05-07 20:01:012792 int64_t writes_size1 = CountWriteBytes(data_writes1);
bnc691fda62016-08-12 00:43:162793 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012794 int64_t reads_size1 = CountReadBytes(data_reads1);
bnc691fda62016-08-12 00:43:162795 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592796
bnc691fda62016-08-12 00:43:162797 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592798 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582799 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
ttuttled9dbc652015-09-29 20:00:592800
2801 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:162802 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592803 ASSERT_FALSE(endpoint.address().empty());
2804 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2805
2806 resolver->rules()->ClearRules();
2807 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2808
2809 TestCompletionCallback callback2;
2810
bnc691fda62016-08-12 00:43:162811 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
ttuttled9dbc652015-09-29 20:00:592812 AuthCredentials(kFoo, kBar), callback2.callback())));
2813
2814 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:162815 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
ttuttled9dbc652015-09-29 20:00:592816 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2817 // The load timing after restart should have a new socket ID, and times after
2818 // those of the first load timing.
2819 EXPECT_LE(load_timing_info1.receive_headers_end,
2820 load_timing_info2.connect_timing.connect_start);
2821 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2822
Ryan Sleevib8d7ea02018-05-07 20:01:012823 int64_t writes_size2 = CountWriteBytes(data_writes2);
bnc691fda62016-08-12 00:43:162824 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012825 int64_t reads_size2 = CountReadBytes(data_reads2);
bnc691fda62016-08-12 00:43:162826 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
ttuttled9dbc652015-09-29 20:00:592827
bnc691fda62016-08-12 00:43:162828 response = trans.GetResponseInfo();
ttuttled9dbc652015-09-29 20:00:592829 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582830 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttled9dbc652015-09-29 20:00:592831 EXPECT_EQ(100, response->headers->GetContentLength());
2832
bnc691fda62016-08-12 00:43:162833 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:592834 ASSERT_FALSE(endpoint.address().empty());
2835 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2836}
2837
David Benjamin83ddfb32018-03-30 01:07:522838// Test that, if the server requests auth indefinitely, HttpNetworkTransaction
2839// will eventually give up.
2840TEST_F(HttpNetworkTransactionTest, BasicAuthForever) {
2841 HttpRequestInfo request;
2842 request.method = "GET";
2843 request.url = GURL("http://www.example.org/");
2844 request.traffic_annotation =
2845 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2846
2847 TestNetLog log;
2848 session_deps_.net_log = &log;
2849 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2850 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2851
2852 MockWrite data_writes[] = {
2853 MockWrite("GET / HTTP/1.1\r\n"
2854 "Host: www.example.org\r\n"
2855 "Connection: keep-alive\r\n\r\n"),
2856 };
2857
2858 MockRead data_reads[] = {
2859 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2860 // Give a couple authenticate options (only the middle one is actually
2861 // supported).
2862 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2863 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2864 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2866 // Large content-length -- won't matter, as connection will be reset.
2867 MockRead("Content-Length: 10000\r\n\r\n"),
2868 MockRead(SYNCHRONOUS, ERR_FAILED),
2869 };
2870
2871 // After calling trans->RestartWithAuth(), this is the request we should
2872 // be issuing -- the final header line contains the credentials.
2873 MockWrite data_writes_restart[] = {
2874 MockWrite("GET / HTTP/1.1\r\n"
2875 "Host: www.example.org\r\n"
2876 "Connection: keep-alive\r\n"
2877 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2878 };
2879
Ryan Sleevib8d7ea02018-05-07 20:01:012880 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin83ddfb32018-03-30 01:07:522881 session_deps_.socket_factory->AddSocketDataProvider(&data);
2882
2883 TestCompletionCallback callback;
2884 int rv = callback.GetResult(
2885 trans.Start(&request, callback.callback(), NetLogWithSource()));
2886
2887 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
2888 for (int i = 0; i < 32; i++) {
2889 // Check the previous response was a 401.
2890 EXPECT_THAT(rv, IsOk());
2891 const HttpResponseInfo* response = trans.GetResponseInfo();
2892 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582893 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
David Benjamin83ddfb32018-03-30 01:07:522894
2895 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:012896 data_reads, data_writes_restart));
David Benjamin83ddfb32018-03-30 01:07:522897 session_deps_.socket_factory->AddSocketDataProvider(
2898 data_restarts.back().get());
2899 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
2900 callback.callback()));
2901 }
2902
2903 // After too many tries, the transaction should have given up.
2904 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
2905}
2906
bncd16676a2016-07-20 16:23:012907TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462908 HttpRequestInfo request;
2909 request.method = "GET";
bncce36dca22015-04-21 22:11:232910 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292911 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:102912 request.traffic_annotation =
2913 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]861fcd52009-08-26 02:33:462914
danakj1fd259a02016-04-16 03:17:092915 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:162916 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:272917
[email protected]861fcd52009-08-26 02:33:462918 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232919 MockWrite(
2920 "GET / HTTP/1.1\r\n"
2921 "Host: www.example.org\r\n"
2922 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462923 };
2924
2925 MockRead data_reads[] = {
2926 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2927 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2929 // Large content-length -- won't matter, as connection will be reset.
2930 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062931 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462932 };
2933
Ryan Sleevib8d7ea02018-05-07 20:01:012934 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:072935 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412936 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462937
tfarina42834112016-09-22 13:38:202938 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:012939 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462940
2941 rv = callback.WaitForResult();
2942 EXPECT_EQ(0, rv);
2943
Ryan Sleevib8d7ea02018-05-07 20:01:012944 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:162945 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:012946 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:162947 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
[email protected]b8015c42013-12-24 15:18:192948
bnc691fda62016-08-12 00:43:162949 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:522950 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:582951 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]861fcd52009-08-26 02:33:462952}
2953
[email protected]2d2697f92009-02-18 21:00:322954// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2955// connection.
bncd16676a2016-07-20 16:23:012956TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182957 // On the second pass, the body read of the auth challenge is synchronous, so
2958 // IsConnectedAndIdle returns false. The socket should still be drained and
2959 // reused. See http://crbug.com/544255.
2960 for (int i = 0; i < 2; ++i) {
2961 HttpRequestInfo request;
2962 request.method = "GET";
2963 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:102964 request.traffic_annotation =
2965 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:322966
mmenkecc2298e2015-12-07 18:20:182967 TestNetLog log;
2968 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092969 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272970
mmenkecc2298e2015-12-07 18:20:182971 MockWrite data_writes[] = {
2972 MockWrite(ASYNC, 0,
2973 "GET / HTTP/1.1\r\n"
2974 "Host: www.example.org\r\n"
2975 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322976
bnc691fda62016-08-12 00:43:162977 // After calling trans.RestartWithAuth(), this is the request we should
mmenkecc2298e2015-12-07 18:20:182978 // be issuing -- the final header line contains the credentials.
2979 MockWrite(ASYNC, 6,
2980 "GET / HTTP/1.1\r\n"
2981 "Host: www.example.org\r\n"
2982 "Connection: keep-alive\r\n"
2983 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2984 };
[email protected]2d2697f92009-02-18 21:00:322985
mmenkecc2298e2015-12-07 18:20:182986 MockRead data_reads[] = {
2987 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2988 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2989 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2990 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2991 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322992
mmenkecc2298e2015-12-07 18:20:182993 // Lastly, the server responds with the actual content.
2994 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2995 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2996 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2997 MockRead(ASYNC, 10, "Hello"),
2998 };
[email protected]2d2697f92009-02-18 21:00:322999
Ryan Sleevib8d7ea02018-05-07 20:01:013000 SequencedSocketData data(data_reads, data_writes);
mmenkecc2298e2015-12-07 18:20:183001 data.set_busy_before_sync_reads(true);
3002 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:463003
mmenkecc2298e2015-12-07 18:20:183004 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323005
bnc691fda62016-08-12 00:43:163006 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203007 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013008 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323009
mmenkecc2298e2015-12-07 18:20:183010 LoadTimingInfo load_timing_info1;
bnc691fda62016-08-12 00:43:163011 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
mmenkecc2298e2015-12-07 18:20:183012 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:323013
bnc691fda62016-08-12 00:43:163014 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183015 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583016 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323017
mmenkecc2298e2015-12-07 18:20:183018 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:253019
bnc691fda62016-08-12 00:43:163020 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3021 callback2.callback());
robpercival214763f2016-07-01 23:27:013022 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323023
mmenkecc2298e2015-12-07 18:20:183024 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:163025 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
mmenkecc2298e2015-12-07 18:20:183026 TestLoadTimingReused(load_timing_info2);
3027 // The load timing after restart should have the same socket ID, and times
3028 // those of the first load timing.
3029 EXPECT_LE(load_timing_info1.receive_headers_end,
3030 load_timing_info2.send_start);
3031 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:323032
bnc691fda62016-08-12 00:43:163033 response = trans.GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:183034 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583035 EXPECT_FALSE(response->auth_challenge.has_value());
mmenkecc2298e2015-12-07 18:20:183036 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323037
mmenkecc2298e2015-12-07 18:20:183038 std::string response_data;
bnc691fda62016-08-12 00:43:163039 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:323040
Ryan Sleevib8d7ea02018-05-07 20:01:013041 int64_t writes_size = CountWriteBytes(data_writes);
bnc691fda62016-08-12 00:43:163042 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
Ryan Sleevib8d7ea02018-05-07 20:01:013043 int64_t reads_size = CountReadBytes(data_reads);
bnc691fda62016-08-12 00:43:163044 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
mmenkecc2298e2015-12-07 18:20:183045 }
[email protected]2d2697f92009-02-18 21:00:323046}
3047
3048// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3049// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:013050TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:423051 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323052 request.method = "GET";
bncce36dca22015-04-21 22:11:233053 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103054 request.traffic_annotation =
3055 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323056
danakj1fd259a02016-04-16 03:17:093057 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273058
[email protected]2d2697f92009-02-18 21:00:323059 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163060 MockWrite("GET / HTTP/1.1\r\n"
3061 "Host: www.example.org\r\n"
3062 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323063
bnc691fda62016-08-12 00:43:163064 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233065 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163066 MockWrite("GET / HTTP/1.1\r\n"
3067 "Host: www.example.org\r\n"
3068 "Connection: keep-alive\r\n"
3069 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323070 };
3071
[email protected]2d2697f92009-02-18 21:00:323072 MockRead data_reads1[] = {
3073 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3074 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:313075 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:323076
3077 // Lastly, the server responds with the actual content.
3078 MockRead("HTTP/1.1 200 OK\r\n"),
3079 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503080 MockRead("Content-Length: 5\r\n\r\n"),
3081 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323082 };
3083
[email protected]2d0a4f92011-05-05 16:38:463084 // An incorrect reconnect would cause this to be read.
3085 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063086 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463087 };
3088
Ryan Sleevib8d7ea02018-05-07 20:01:013089 StaticSocketDataProvider data1(data_reads1, data_writes1);
3090 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073091 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3092 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323093
[email protected]49639fa2011-12-20 23:22:413094 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323095
bnc691fda62016-08-12 00:43:163096 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203097 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013098 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323099
3100 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013101 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323102
bnc691fda62016-08-12 00:43:163103 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523104 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583105 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323106
[email protected]49639fa2011-12-20 23:22:413107 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323108
bnc691fda62016-08-12 00:43:163109 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013110 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323111
3112 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013113 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323114
bnc691fda62016-08-12 00:43:163115 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523116 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583117 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503118 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323119}
3120
3121// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3122// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:013123TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:423124 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:323125 request.method = "GET";
bncce36dca22015-04-21 22:11:233126 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103127 request.traffic_annotation =
3128 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d2697f92009-02-18 21:00:323129
danakj1fd259a02016-04-16 03:17:093130 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273131
[email protected]2d2697f92009-02-18 21:00:323132 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:163133 MockWrite("GET / HTTP/1.1\r\n"
3134 "Host: www.example.org\r\n"
3135 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323136
bnc691fda62016-08-12 00:43:163137 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:233138 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:163139 MockWrite("GET / HTTP/1.1\r\n"
3140 "Host: www.example.org\r\n"
3141 "Connection: keep-alive\r\n"
3142 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323143 };
3144
3145 // Respond with 5 kb of response body.
3146 std::string large_body_string("Unauthorized");
3147 large_body_string.append(5 * 1024, ' ');
3148 large_body_string.append("\r\n");
3149
3150 MockRead data_reads1[] = {
3151 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3152 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3153 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3154 // 5134 = 12 + 5 * 1024 + 2
3155 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063156 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:323157
3158 // Lastly, the server responds with the actual content.
3159 MockRead("HTTP/1.1 200 OK\r\n"),
3160 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503161 MockRead("Content-Length: 5\r\n\r\n"),
3162 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:323163 };
3164
[email protected]2d0a4f92011-05-05 16:38:463165 // An incorrect reconnect would cause this to be read.
3166 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:063167 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:463168 };
3169
Ryan Sleevib8d7ea02018-05-07 20:01:013170 StaticSocketDataProvider data1(data_reads1, data_writes1);
3171 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:073172 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3173 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:323174
[email protected]49639fa2011-12-20 23:22:413175 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323176
bnc691fda62016-08-12 00:43:163177 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203178 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013179 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323180
3181 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013182 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323183
bnc691fda62016-08-12 00:43:163184 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523185 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583186 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323187
[email protected]49639fa2011-12-20 23:22:413188 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323189
bnc691fda62016-08-12 00:43:163190 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013191 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:323192
3193 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013194 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:323195
bnc691fda62016-08-12 00:43:163196 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523197 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583198 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503199 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:323200}
3201
3202// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:313203// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:013204TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:313205 HttpRequestInfo request;
3206 request.method = "GET";
bncce36dca22015-04-21 22:11:233207 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103208 request.traffic_annotation =
3209 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]11203f012009-11-12 23:02:313210
danakj1fd259a02016-04-16 03:17:093211 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273212
[email protected]11203f012009-11-12 23:02:313213 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233214 MockWrite(
3215 "GET / HTTP/1.1\r\n"
3216 "Host: www.example.org\r\n"
3217 "Connection: keep-alive\r\n\r\n"),
3218 // This simulates the seemingly successful write to a closed connection
3219 // if the bug is not fixed.
3220 MockWrite(
3221 "GET / HTTP/1.1\r\n"
3222 "Host: www.example.org\r\n"
3223 "Connection: keep-alive\r\n"
3224 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313225 };
3226
3227 MockRead data_reads1[] = {
3228 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3229 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3230 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3231 MockRead("Content-Length: 14\r\n\r\n"),
3232 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:063233 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:313234 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:063235 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:313236 };
3237
bnc691fda62016-08-12 00:43:163238 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]11203f012009-11-12 23:02:313239 // be issuing -- the final header line contains the credentials.
3240 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233241 MockWrite(
3242 "GET / HTTP/1.1\r\n"
3243 "Host: www.example.org\r\n"
3244 "Connection: keep-alive\r\n"
3245 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:313246 };
3247
3248 // Lastly, the server responds with the actual content.
3249 MockRead data_reads2[] = {
3250 MockRead("HTTP/1.1 200 OK\r\n"),
3251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:503252 MockRead("Content-Length: 5\r\n\r\n"),
3253 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:313254 };
3255
Ryan Sleevib8d7ea02018-05-07 20:01:013256 StaticSocketDataProvider data1(data_reads1, data_writes1);
3257 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:073258 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3259 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:313260
[email protected]49639fa2011-12-20 23:22:413261 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:313262
bnc691fda62016-08-12 00:43:163263 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:203264 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013265 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313266
3267 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013268 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313269
bnc691fda62016-08-12 00:43:163270 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523271 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583272 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]11203f012009-11-12 23:02:313273
[email protected]49639fa2011-12-20 23:22:413274 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:313275
bnc691fda62016-08-12 00:43:163276 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013277 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:313278
3279 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013280 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:313281
bnc691fda62016-08-12 00:43:163282 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:523283 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:583284 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0b0bf032010-09-21 18:08:503285 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:313286}
3287
[email protected]394816e92010-08-03 07:38:593288// Test the request-challenge-retry sequence for basic auth, over a connection
3289// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013290TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:013291 HttpRequestInfo request;
3292 request.method = "GET";
bncce36dca22015-04-21 22:11:233293 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:013294 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293295 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103296 request.traffic_annotation =
3297 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle34f63b52015-03-05 04:33:013298
3299 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593300 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493301 ProxyResolutionService::CreateFixedFromPacResult(
3302 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513303 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:013304 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093305 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013306
3307 // Since we have proxy, should try to establish tunnel.
3308 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543309 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173310 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543311 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013312 };
3313
mmenkee71e15332015-10-07 16:39:543314 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:013315 // connection.
3316 MockRead data_reads1[] = {
3317 // No credentials.
3318 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3319 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:543320 };
ttuttle34f63b52015-03-05 04:33:013321
mmenkee71e15332015-10-07 16:39:543322 // Since the first connection couldn't be reused, need to establish another
3323 // once given credentials.
3324 MockWrite data_writes2[] = {
3325 // After calling trans->RestartWithAuth(), this is the request we should
3326 // be issuing -- the final header line contains the credentials.
3327 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173328 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543329 "Proxy-Connection: keep-alive\r\n"
3330 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3331
3332 MockWrite("GET / HTTP/1.1\r\n"
3333 "Host: www.example.org\r\n"
3334 "Connection: keep-alive\r\n\r\n"),
3335 };
3336
3337 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:013338 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3339
3340 MockRead("HTTP/1.1 200 OK\r\n"),
3341 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3342 MockRead("Content-Length: 5\r\n\r\n"),
3343 MockRead(SYNCHRONOUS, "hello"),
3344 };
3345
Ryan Sleevib8d7ea02018-05-07 20:01:013346 StaticSocketDataProvider data1(data_reads1, data_writes1);
ttuttle34f63b52015-03-05 04:33:013347 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013348 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543349 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:013350 SSLSocketDataProvider ssl(ASYNC, OK);
3351 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3352
3353 TestCompletionCallback callback1;
3354
bnc87dcefc2017-05-25 12:47:583355 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193356 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
ttuttle34f63b52015-03-05 04:33:013357
3358 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013359 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013360
3361 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013362 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543363 auto entries = log.GetEntries();
ttuttle34f63b52015-03-05 04:33:013364 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003365 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3366 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013367 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003368 entries, pos,
3369 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3370 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013371
3372 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523373 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013374 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:523375 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:013376 EXPECT_EQ(407, response->headers->response_code());
3377 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583378 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013379
3380 LoadTimingInfo load_timing_info;
3381 // CONNECT requests and responses are handled at the connect job level, so
3382 // the transaction does not yet have a connection.
3383 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3384
3385 TestCompletionCallback callback2;
3386
3387 rv =
3388 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013389 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:013390
3391 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:013392 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:013393
3394 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:523395 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:013396
3397 EXPECT_TRUE(response->headers->IsKeepAlive());
3398 EXPECT_EQ(200, response->headers->response_code());
3399 EXPECT_EQ(5, response->headers->GetContentLength());
3400 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3401
3402 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583403 EXPECT_FALSE(response->auth_challenge.has_value());
ttuttle34f63b52015-03-05 04:33:013404
3405 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3406 TestLoadTimingNotReusedWithPac(load_timing_info,
3407 CONNECT_TIMING_HAS_SSL_TIMES);
3408
3409 trans.reset();
3410 session->CloseAllConnections();
3411}
3412
3413// Test the request-challenge-retry sequence for basic auth, over a connection
3414// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013415TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:593416 HttpRequestInfo request;
3417 request.method = "GET";
bncce36dca22015-04-21 22:11:233418 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:593419 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293420 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103421 request.traffic_annotation =
3422 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]394816e92010-08-03 07:38:593423
[email protected]cb9bf6ca2011-01-28 13:15:273424 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593425 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493426 ProxyResolutionService::CreateFixedFromPacResult(
3427 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513428 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073429 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093430 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:273431
[email protected]394816e92010-08-03 07:38:593432 // Since we have proxy, should try to establish tunnel.
3433 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:543434 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173435 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543436 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:113437 };
3438
mmenkee71e15332015-10-07 16:39:543439 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:083440 // connection.
3441 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:543442 // No credentials.
3443 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3444 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3445 MockRead("Proxy-Connection: close\r\n\r\n"),
3446 };
mmenkee0b5c882015-08-26 20:29:113447
mmenkee71e15332015-10-07 16:39:543448 MockWrite data_writes2[] = {
3449 // After calling trans->RestartWithAuth(), this is the request we should
3450 // be issuing -- the final header line contains the credentials.
3451 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173452 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543453 "Proxy-Connection: keep-alive\r\n"
3454 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:083455
mmenkee71e15332015-10-07 16:39:543456 MockWrite("GET / HTTP/1.1\r\n"
3457 "Host: www.example.org\r\n"
3458 "Connection: keep-alive\r\n\r\n"),
3459 };
3460
3461 MockRead data_reads2[] = {
3462 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3463
3464 MockRead("HTTP/1.1 200 OK\r\n"),
3465 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3466 MockRead("Content-Length: 5\r\n\r\n"),
3467 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:593468 };
3469
Ryan Sleevib8d7ea02018-05-07 20:01:013470 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:073471 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013472 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543473 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:063474 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:593476
[email protected]49639fa2011-12-20 23:22:413477 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:593478
bnc87dcefc2017-05-25 12:47:583479 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193480 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:503481
[email protected]49639fa2011-12-20 23:22:413482 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013483 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:593484
3485 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013486 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:543487 auto entries = log.GetEntries();
[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
Eric Roman79cc7552019-07-19 02:17:543609 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233610 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003611 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3612 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233613 ExpectLogContainsSomewhere(
3614 entries, pos,
mikecirone8b85c432016-09-08 19:11:003615 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3616 NetLogEventPhase::NONE);
ttuttle34f63b52015-03-05 04:33:013617
bnc691fda62016-08-12 00:43:163618 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233619 ASSERT_TRUE(response);
3620 ASSERT_TRUE(response->headers);
3621 EXPECT_TRUE(response->headers->IsKeepAlive());
3622 EXPECT_EQ(407, response->headers->response_code());
3623 EXPECT_EQ(10, response->headers->GetContentLength());
3624 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583625 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013626
mmenked39192ee2015-12-09 00:57:233627 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013628
mmenked39192ee2015-12-09 00:57:233629 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163630 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3631 callback2.callback());
robpercival214763f2016-07-01 23:27:013632 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013633
bnc691fda62016-08-12 00:43:163634 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233635 ASSERT_TRUE(response);
3636 ASSERT_TRUE(response->headers);
3637 EXPECT_TRUE(response->headers->IsKeepAlive());
3638 EXPECT_EQ(407, response->headers->response_code());
3639 EXPECT_EQ(10, response->headers->GetContentLength());
3640 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583641 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
ttuttle34f63b52015-03-05 04:33:013642
mmenked39192ee2015-12-09 00:57:233643 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3644 // out of scope.
3645 session->CloseAllConnections();
3646 }
ttuttle34f63b52015-03-05 04:33:013647}
3648
3649// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3650// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013651TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233652 // On the second pass, the body read of the auth challenge is synchronous, so
3653 // IsConnectedAndIdle returns false. The socket should still be drained and
3654 // reused. See http://crbug.com/544255.
3655 for (int i = 0; i < 2; ++i) {
3656 HttpRequestInfo request;
3657 request.method = "GET";
3658 request.url = GURL("https://www.example.org/");
3659 // Ensure that proxy authentication is attempted even
3660 // when the no authentication data flag is set.
3661 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103662 request.traffic_annotation =
3663 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233664
3665 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593666 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493667 ProxyResolutionService::CreateFixed("myproxy:70",
3668 TRAFFIC_ANNOTATION_FOR_TESTS);
mmenked39192ee2015-12-09 00:57:233669 BoundTestNetLog log;
3670 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093671 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233672
bnc691fda62016-08-12 00:43:163673 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenked39192ee2015-12-09 00:57:233674
3675 // Since we have proxy, should try to establish tunnel.
3676 MockWrite data_writes1[] = {
3677 MockWrite(ASYNC, 0,
3678 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3679 "Host: www.example.org:443\r\n"
3680 "Proxy-Connection: keep-alive\r\n\r\n"),
3681
bnc691fda62016-08-12 00:43:163682 // After calling trans.RestartWithAuth(), this is the request we should
mmenked39192ee2015-12-09 00:57:233683 // be issuing -- the final header line contains the credentials.
3684 MockWrite(ASYNC, 3,
3685 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3686 "Host: www.example.org:443\r\n"
3687 "Proxy-Connection: keep-alive\r\n"
3688 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3689 };
3690
3691 // The proxy responds to the connect with a 407, using a persistent
3692 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3693 MockRead data_reads1[] = {
3694 // No credentials.
3695 MockRead(ASYNC, 1,
3696 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3697 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3698 "Content-Length: 10\r\n\r\n"),
3699 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3700
3701 // Wrong credentials (wrong password).
3702 MockRead(ASYNC, 4,
3703 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3704 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3705 "Content-Length: 10\r\n\r\n"),
3706 // No response body because the test stops reading here.
3707 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3708 };
3709
Ryan Sleevib8d7ea02018-05-07 20:01:013710 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233711 data1.set_busy_before_sync_reads(true);
3712 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3713
3714 TestCompletionCallback callback1;
3715
bnc691fda62016-08-12 00:43:163716 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013717 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233718
Eric Roman79cc7552019-07-19 02:17:543719 auto entries = log.GetEntries();
mmenked39192ee2015-12-09 00:57:233720 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003721 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3722 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233723 ExpectLogContainsSomewhere(
3724 entries, pos,
mikecirone8b85c432016-09-08 19:11:003725 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3726 NetLogEventPhase::NONE);
mmenked39192ee2015-12-09 00:57:233727
bnc691fda62016-08-12 00:43:163728 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233729 ASSERT_TRUE(response);
3730 ASSERT_TRUE(response->headers);
3731 EXPECT_TRUE(response->headers->IsKeepAlive());
3732 EXPECT_EQ(407, response->headers->response_code());
3733 EXPECT_EQ(10, response->headers->GetContentLength());
3734 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583735 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503736 EXPECT_FALSE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233737
3738 TestCompletionCallback callback2;
3739
3740 // Wrong password (should be "bar").
bnc691fda62016-08-12 00:43:163741 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
3742 callback2.callback());
robpercival214763f2016-07-01 23:27:013743 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233744
bnc691fda62016-08-12 00:43:163745 response = trans.GetResponseInfo();
mmenked39192ee2015-12-09 00:57:233746 ASSERT_TRUE(response);
3747 ASSERT_TRUE(response->headers);
3748 EXPECT_TRUE(response->headers->IsKeepAlive());
3749 EXPECT_EQ(407, response->headers->response_code());
3750 EXPECT_EQ(10, response->headers->GetContentLength());
3751 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583752 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:503753 EXPECT_TRUE(response->did_use_http_auth);
mmenked39192ee2015-12-09 00:57:233754
3755 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3756 // out of scope.
3757 session->CloseAllConnections();
3758 }
3759}
3760
3761// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3762// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3763// the case the server sends extra data on the original socket, so it can't be
3764// reused.
bncd16676a2016-07-20 16:23:013765TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273766 HttpRequestInfo request;
3767 request.method = "GET";
bncce36dca22015-04-21 22:11:233768 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273769 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293770 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103771 request.traffic_annotation =
3772 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273773
[email protected]2d2697f92009-02-18 21:00:323774 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:593775 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:493776 ProxyResolutionService::CreateFixedFromPacResult(
3777 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:513778 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073779 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093780 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323781
[email protected]2d2697f92009-02-18 21:00:323782 // Since we have proxy, should try to establish tunnel.
3783 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233784 MockWrite(ASYNC, 0,
3785 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173786 "Host: www.example.org:443\r\n"
3787 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233788 };
[email protected]2d2697f92009-02-18 21:00:323789
mmenked39192ee2015-12-09 00:57:233790 // The proxy responds to the connect with a 407, using a persistent, but sends
3791 // extra data, so the socket cannot be reused.
3792 MockRead data_reads1[] = {
3793 // No credentials.
3794 MockRead(ASYNC, 1,
3795 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3796 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3797 "Content-Length: 10\r\n\r\n"),
3798 MockRead(SYNCHRONOUS, 2, "0123456789"),
3799 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3800 };
3801
3802 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233803 // After calling trans->RestartWithAuth(), this is the request we should
3804 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233805 MockWrite(ASYNC, 0,
3806 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173807 "Host: www.example.org:443\r\n"
3808 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233809 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3810
3811 MockWrite(ASYNC, 2,
3812 "GET / HTTP/1.1\r\n"
3813 "Host: www.example.org\r\n"
3814 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323815 };
3816
mmenked39192ee2015-12-09 00:57:233817 MockRead data_reads2[] = {
3818 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323819
mmenked39192ee2015-12-09 00:57:233820 MockRead(ASYNC, 3,
3821 "HTTP/1.1 200 OK\r\n"
3822 "Content-Type: text/html; charset=iso-8859-1\r\n"
3823 "Content-Length: 5\r\n\r\n"),
3824 // No response body because the test stops reading here.
3825 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323826 };
3827
Ryan Sleevib8d7ea02018-05-07 20:01:013828 SequencedSocketData data1(data_reads1, data_writes1);
mmenked39192ee2015-12-09 00:57:233829 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073830 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013831 SequencedSocketData data2(data_reads2, data_writes2);
mmenked39192ee2015-12-09 00:57:233832 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3833 SSLSocketDataProvider ssl(ASYNC, OK);
3834 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323835
[email protected]49639fa2011-12-20 23:22:413836 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323837
bnc87dcefc2017-05-25 12:47:583838 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:193839 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d2697f92009-02-18 21:00:323840
mmenked39192ee2015-12-09 00:57:233841 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013842 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233843
Eric Roman79cc7552019-07-19 02:17:543844 auto entries = log.GetEntries();
[email protected]dbb83db2010-05-11 18:13:393845 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:003846 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3847 NetLogEventPhase::NONE);
[email protected]dbb83db2010-05-11 18:13:393848 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403849 entries, pos,
mikecirone8b85c432016-09-08 19:11:003850 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3851 NetLogEventPhase::NONE);
[email protected]2d2697f92009-02-18 21:00:323852
[email protected]1c773ea12009-04-28 19:58:423853 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243854 ASSERT_TRUE(response);
3855 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323856 EXPECT_TRUE(response->headers->IsKeepAlive());
3857 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423858 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:583859 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]2d2697f92009-02-18 21:00:323860
mmenked39192ee2015-12-09 00:57:233861 LoadTimingInfo load_timing_info;
3862 // CONNECT requests and responses are handled at the connect job level, so
3863 // the transaction does not yet have a connection.
3864 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3865
[email protected]49639fa2011-12-20 23:22:413866 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323867
mmenked39192ee2015-12-09 00:57:233868 rv =
3869 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013870 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323871
[email protected]2d2697f92009-02-18 21:00:323872 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233873 EXPECT_EQ(200, response->headers->response_code());
3874 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423875 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133876
mmenked39192ee2015-12-09 00:57:233877 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:583878 EXPECT_FALSE(response->auth_challenge.has_value());
mmenked39192ee2015-12-09 00:57:233879
3880 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3881 TestLoadTimingNotReusedWithPac(load_timing_info,
3882 CONNECT_TIMING_HAS_SSL_TIMES);
3883
3884 trans.reset();
[email protected]102e27c2011-02-23 01:01:313885 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323886}
3887
mmenkee71e15332015-10-07 16:39:543888// Test the case a proxy closes a socket while the challenge body is being
3889// drained.
bncd16676a2016-07-20 16:23:013890TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543891 HttpRequestInfo request;
3892 request.method = "GET";
3893 request.url = GURL("https://www.example.org/");
3894 // Ensure that proxy authentication is attempted even
3895 // when the no authentication data flag is set.
3896 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:103897 request.traffic_annotation =
3898 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenkee71e15332015-10-07 16:39:543899
3900 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493901 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3902 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:093903 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543904
bnc691fda62016-08-12 00:43:163905 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkee71e15332015-10-07 16:39:543906
3907 // Since we have proxy, should try to establish tunnel.
3908 MockWrite data_writes1[] = {
3909 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173910 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543911 "Proxy-Connection: keep-alive\r\n\r\n"),
3912 };
3913
3914 // The proxy responds to the connect with a 407, using a persistent
3915 // connection.
3916 MockRead data_reads1[] = {
3917 // No credentials.
3918 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3919 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3920 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3921 // Server hands up in the middle of the body.
3922 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3923 };
3924
3925 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:163926 // After calling trans.RestartWithAuth(), this is the request we should
mmenkee71e15332015-10-07 16:39:543927 // be issuing -- the final header line contains the credentials.
3928 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173929 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543930 "Proxy-Connection: keep-alive\r\n"
3931 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3932
3933 MockWrite("GET / HTTP/1.1\r\n"
3934 "Host: www.example.org\r\n"
3935 "Connection: keep-alive\r\n\r\n"),
3936 };
3937
3938 MockRead data_reads2[] = {
3939 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3940
3941 MockRead("HTTP/1.1 200 OK\r\n"),
3942 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3943 MockRead("Content-Length: 5\r\n\r\n"),
3944 MockRead(SYNCHRONOUS, "hello"),
3945 };
3946
Ryan Sleevib8d7ea02018-05-07 20:01:013947 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenkee71e15332015-10-07 16:39:543948 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:013949 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenkee71e15332015-10-07 16:39:543950 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3951 SSLSocketDataProvider ssl(ASYNC, OK);
3952 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3953
3954 TestCompletionCallback callback;
3955
tfarina42834112016-09-22 13:38:203956 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:013957 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543958
bnc691fda62016-08-12 00:43:163959 const HttpResponseInfo* response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543960 ASSERT_TRUE(response);
3961 ASSERT_TRUE(response->headers);
3962 EXPECT_TRUE(response->headers->IsKeepAlive());
3963 EXPECT_EQ(407, response->headers->response_code());
Emily Starkf2c9bbd2019-04-09 17:08:583964 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
mmenkee71e15332015-10-07 16:39:543965
bnc691fda62016-08-12 00:43:163966 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013967 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543968
bnc691fda62016-08-12 00:43:163969 response = trans.GetResponseInfo();
mmenkee71e15332015-10-07 16:39:543970 ASSERT_TRUE(response);
3971 ASSERT_TRUE(response->headers);
3972 EXPECT_TRUE(response->headers->IsKeepAlive());
3973 EXPECT_EQ(200, response->headers->response_code());
3974 std::string body;
bnc691fda62016-08-12 00:43:163975 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
mmenkee71e15332015-10-07 16:39:543976 EXPECT_EQ("hello", body);
3977}
3978
[email protected]a8e9b162009-03-12 00:06:443979// Test that we don't read the response body when we fail to establish a tunnel,
3980// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013981TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273982 HttpRequestInfo request;
3983 request.method = "GET";
bncce36dca22015-04-21 22:11:233984 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:103985 request.traffic_annotation =
3986 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:273987
[email protected]a8e9b162009-03-12 00:06:443988 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:493989 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
3990 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a8e9b162009-03-12 00:06:443991
danakj1fd259a02016-04-16 03:17:093992 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443993
bnc691fda62016-08-12 00:43:163994 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]a8e9b162009-03-12 00:06:443995
[email protected]a8e9b162009-03-12 00:06:443996 // Since we have proxy, should try to establish tunnel.
3997 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173998 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3999 "Host: www.example.org:443\r\n"
4000 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:444001 };
4002
4003 // The proxy responds to the connect with a 407.
4004 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:244005 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4006 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4007 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234008 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:244009 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:444010 };
4011
Ryan Sleevib8d7ea02018-05-07 20:01:014012 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:074013 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:444014
[email protected]49639fa2011-12-20 23:22:414015 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:444016
tfarina42834112016-09-22 13:38:204017 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014018 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:444019
4020 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014021 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:444022
bnc691fda62016-08-12 00:43:164023 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244024 ASSERT_TRUE(response);
4025 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:444026 EXPECT_TRUE(response->headers->IsKeepAlive());
4027 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:424028 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:444029
4030 std::string response_data;
bnc691fda62016-08-12 00:43:164031 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014032 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:184033
4034 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:314035 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:444036}
4037
ttuttle7933c112015-01-06 00:55:244038// Test that we don't pass extraneous headers from the proxy's response to the
4039// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:014040TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:244041 HttpRequestInfo request;
4042 request.method = "GET";
bncce36dca22015-04-21 22:11:234043 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104044 request.traffic_annotation =
4045 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244046
4047 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:494048 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4049 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
ttuttle7933c112015-01-06 00:55:244050
danakj1fd259a02016-04-16 03:17:094051 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:244052
bnc691fda62016-08-12 00:43:164053 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ttuttle7933c112015-01-06 00:55:244054
4055 // Since we have proxy, should try to establish tunnel.
4056 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:174057 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4058 "Host: www.example.org:443\r\n"
4059 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:244060 };
4061
4062 // The proxy responds to the connect with a 407.
4063 MockRead data_reads[] = {
4064 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4065 MockRead("X-Foo: bar\r\n"),
4066 MockRead("Set-Cookie: foo=bar\r\n"),
4067 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4068 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:234069 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:244070 };
4071
Ryan Sleevib8d7ea02018-05-07 20:01:014072 StaticSocketDataProvider data(data_reads, data_writes);
ttuttle7933c112015-01-06 00:55:244073 session_deps_.socket_factory->AddSocketDataProvider(&data);
4074
4075 TestCompletionCallback callback;
4076
tfarina42834112016-09-22 13:38:204077 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014078 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:244079
4080 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014081 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:244082
bnc691fda62016-08-12 00:43:164083 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttle7933c112015-01-06 00:55:244084 ASSERT_TRUE(response);
4085 ASSERT_TRUE(response->headers);
4086 EXPECT_TRUE(response->headers->IsKeepAlive());
4087 EXPECT_EQ(407, response->headers->response_code());
4088 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4089 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
4090 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
4091
4092 std::string response_data;
bnc691fda62016-08-12 00:43:164093 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:014094 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:244095
4096 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4097 session->CloseAllConnections();
4098}
4099
[email protected]8fdbcd22010-05-05 02:54:524100// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
4101// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:014102TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:524103 HttpRequestInfo request;
4104 request.method = "GET";
bncce36dca22015-04-21 22:11:234105 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104106 request.traffic_annotation =
4107 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8fdbcd22010-05-05 02:54:524108
[email protected]cb9bf6ca2011-01-28 13:15:274109 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:094110 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:164111 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:274112
[email protected]8fdbcd22010-05-05 02:54:524113 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234114 MockWrite(
4115 "GET / HTTP/1.1\r\n"
4116 "Host: www.example.org\r\n"
4117 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:524118 };
4119
4120 MockRead data_reads1[] = {
4121 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
4122 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4123 // Large content-length -- won't matter, as connection will be reset.
4124 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064125 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:524126 };
4127
Ryan Sleevib8d7ea02018-05-07 20:01:014128 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074129 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:524130
[email protected]49639fa2011-12-20 23:22:414131 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:524132
tfarina42834112016-09-22 13:38:204133 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014134 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:524135
4136 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:014137 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:524138}
4139
[email protected]7a67a8152010-11-05 18:31:104140// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
4141// through a non-authenticating proxy. The request should fail with
4142// ERR_UNEXPECTED_PROXY_AUTH.
4143// Note that it is impossible to detect if an HTTP server returns a 407 through
4144// a non-authenticating proxy - there is nothing to indicate whether the
4145// response came from the proxy or the server, so it is treated as if the proxy
4146// issued the challenge.
bncd16676a2016-07-20 16:23:014147TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:274148 HttpRequestInfo request;
4149 request.method = "GET";
bncce36dca22015-04-21 22:11:234150 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104151 request.traffic_annotation =
4152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:274153
Ramin Halavatica8d5252018-03-12 05:33:494154 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
4155 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:514156 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074157 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094158 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:104159
[email protected]7a67a8152010-11-05 18:31:104160 // Since we have proxy, should try to establish tunnel.
4161 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174162 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4163 "Host: www.example.org:443\r\n"
4164 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104165
rsleevidb16bb02015-11-12 23:47:174166 MockWrite("GET / HTTP/1.1\r\n"
4167 "Host: www.example.org\r\n"
4168 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:104169 };
4170
4171 MockRead data_reads1[] = {
4172 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4173
4174 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
4175 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4176 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:064177 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:104178 };
4179
Ryan Sleevib8d7ea02018-05-07 20:01:014180 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:074181 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064182 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074183 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:104184
[email protected]49639fa2011-12-20 23:22:414185 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:104186
bnc691fda62016-08-12 00:43:164187 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]7a67a8152010-11-05 18:31:104188
bnc691fda62016-08-12 00:43:164189 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014190 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:104191
4192 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014193 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
Eric Roman79cc7552019-07-19 02:17:544194 auto entries = log.GetEntries();
[email protected]7a67a8152010-11-05 18:31:104195 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:004196 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4197 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104198 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:404199 entries, pos,
mikecirone8b85c432016-09-08 19:11:004200 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4201 NetLogEventPhase::NONE);
[email protected]7a67a8152010-11-05 18:31:104202}
[email protected]2df19bb2010-08-25 20:13:464203
mmenke2a1781d2015-10-07 19:25:334204// Test a proxy auth scheme that allows default credentials and a proxy server
4205// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:014206TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334207 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
4208 HttpRequestInfo request;
4209 request.method = "GET";
4210 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104211 request.traffic_annotation =
4212 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334213
4214 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594215 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494216 ProxyResolutionService::CreateFixedFromPacResult(
4217 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334218
Jeremy Roman0579ed62017-08-29 15:56:194219 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334220 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194221 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334222 mock_handler->set_allows_default_credentials(true);
4223 auth_handler_factory->AddMockHandler(mock_handler.release(),
4224 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484225 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334226
4227 // Add NetLog just so can verify load timing information gets a NetLog ID.
4228 NetLog net_log;
4229 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094230 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334231
4232 // Since we have proxy, should try to establish tunnel.
4233 MockWrite data_writes1[] = {
4234 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174235 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334236 "Proxy-Connection: keep-alive\r\n\r\n"),
4237 };
4238
4239 // The proxy responds to the connect with a 407, using a non-persistent
4240 // connection.
4241 MockRead data_reads1[] = {
4242 // No credentials.
4243 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4244 MockRead("Proxy-Authenticate: Mock\r\n"),
4245 MockRead("Proxy-Connection: close\r\n\r\n"),
4246 };
4247
4248 // Since the first connection couldn't be reused, need to establish another
4249 // once given credentials.
4250 MockWrite data_writes2[] = {
4251 // After calling trans->RestartWithAuth(), this is the request we should
4252 // be issuing -- the final header line contains the credentials.
4253 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174254 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334255 "Proxy-Connection: keep-alive\r\n"
4256 "Proxy-Authorization: auth_token\r\n\r\n"),
4257
4258 MockWrite("GET / HTTP/1.1\r\n"
4259 "Host: www.example.org\r\n"
4260 "Connection: keep-alive\r\n\r\n"),
4261 };
4262
4263 MockRead data_reads2[] = {
4264 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4265
4266 MockRead("HTTP/1.1 200 OK\r\n"),
4267 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4268 MockRead("Content-Length: 5\r\n\r\n"),
4269 MockRead(SYNCHRONOUS, "hello"),
4270 };
4271
Ryan Sleevib8d7ea02018-05-07 20:01:014272 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334273 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014274 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334275 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4276 SSLSocketDataProvider ssl(ASYNC, OK);
4277 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4278
bnc87dcefc2017-05-25 12:47:584279 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194280 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334281
4282 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204283 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014284 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334285
4286 const HttpResponseInfo* response = trans->GetResponseInfo();
4287 ASSERT_TRUE(response);
4288 ASSERT_TRUE(response->headers);
4289 EXPECT_FALSE(response->headers->IsKeepAlive());
4290 EXPECT_EQ(407, response->headers->response_code());
4291 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4292 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584293 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334294
4295 LoadTimingInfo load_timing_info;
4296 // CONNECT requests and responses are handled at the connect job level, so
4297 // the transaction does not yet have a connection.
4298 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4299
4300 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014301 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334302 response = trans->GetResponseInfo();
4303 ASSERT_TRUE(response);
4304 ASSERT_TRUE(response->headers);
4305 EXPECT_TRUE(response->headers->IsKeepAlive());
4306 EXPECT_EQ(200, response->headers->response_code());
4307 EXPECT_EQ(5, response->headers->GetContentLength());
4308 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4309
4310 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584311 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334312
4313 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4314 TestLoadTimingNotReusedWithPac(load_timing_info,
4315 CONNECT_TIMING_HAS_SSL_TIMES);
4316
4317 trans.reset();
4318 session->CloseAllConnections();
4319}
4320
4321// Test a proxy auth scheme that allows default credentials and a proxy server
4322// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:014323TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334324 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
4325 HttpRequestInfo request;
4326 request.method = "GET";
4327 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104328 request.traffic_annotation =
4329 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334330
4331 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594332 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494333 ProxyResolutionService::CreateFixedFromPacResult(
4334 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334335
Jeremy Roman0579ed62017-08-29 15:56:194336 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334337 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194338 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334339 mock_handler->set_allows_default_credentials(true);
4340 auth_handler_factory->AddMockHandler(mock_handler.release(),
4341 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484342 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334343
4344 // Add NetLog just so can verify load timing information gets a NetLog ID.
4345 NetLog net_log;
4346 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094347 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334348
4349 // Should try to establish tunnel.
4350 MockWrite data_writes1[] = {
4351 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174352 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334353 "Proxy-Connection: keep-alive\r\n\r\n"),
4354
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"
4358 "Proxy-Authorization: auth_token\r\n\r\n"),
4359 };
4360
4361 // The proxy responds to the connect with a 407, using a non-persistent
4362 // connection.
4363 MockRead data_reads1[] = {
4364 // No credentials.
4365 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4366 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4367 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4368 };
4369
4370 // Since the first connection was closed, need to establish another once given
4371 // credentials.
4372 MockWrite data_writes2[] = {
4373 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174374 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334375 "Proxy-Connection: keep-alive\r\n"
4376 "Proxy-Authorization: auth_token\r\n\r\n"),
4377
4378 MockWrite("GET / HTTP/1.1\r\n"
4379 "Host: www.example.org\r\n"
4380 "Connection: keep-alive\r\n\r\n"),
4381 };
4382
4383 MockRead data_reads2[] = {
4384 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
4385
4386 MockRead("HTTP/1.1 200 OK\r\n"),
4387 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4388 MockRead("Content-Length: 5\r\n\r\n"),
4389 MockRead(SYNCHRONOUS, "hello"),
4390 };
4391
Ryan Sleevib8d7ea02018-05-07 20:01:014392 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334393 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014394 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334395 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4396 SSLSocketDataProvider ssl(ASYNC, OK);
4397 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4398
bnc87dcefc2017-05-25 12:47:584399 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194400 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334401
4402 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204403 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014404 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334405
4406 const HttpResponseInfo* response = trans->GetResponseInfo();
4407 ASSERT_TRUE(response);
4408 ASSERT_TRUE(response->headers);
4409 EXPECT_TRUE(response->headers->IsKeepAlive());
4410 EXPECT_EQ(407, response->headers->response_code());
4411 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4412 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584413 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334414
4415 LoadTimingInfo load_timing_info;
4416 // CONNECT requests and responses are handled at the connect job level, so
4417 // the transaction does not yet have a connection.
4418 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4419
4420 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014421 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334422
4423 response = trans->GetResponseInfo();
4424 ASSERT_TRUE(response);
4425 ASSERT_TRUE(response->headers);
4426 EXPECT_TRUE(response->headers->IsKeepAlive());
4427 EXPECT_EQ(200, response->headers->response_code());
4428 EXPECT_EQ(5, response->headers->GetContentLength());
4429 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4430
4431 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:584432 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334433
4434 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4435 TestLoadTimingNotReusedWithPac(load_timing_info,
4436 CONNECT_TIMING_HAS_SSL_TIMES);
4437
4438 trans.reset();
4439 session->CloseAllConnections();
4440}
4441
4442// Test a proxy auth scheme that allows default credentials and a proxy server
4443// that hangs up when credentials are initially sent, and hangs up again when
4444// they are retried.
bncd16676a2016-07-20 16:23:014445TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334446 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
4447 HttpRequestInfo request;
4448 request.method = "GET";
4449 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104450 request.traffic_annotation =
4451 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334452
4453 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594454 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494455 ProxyResolutionService::CreateFixedFromPacResult(
4456 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334457
Jeremy Roman0579ed62017-08-29 15:56:194458 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334459 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194460 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334461 mock_handler->set_allows_default_credentials(true);
4462 auth_handler_factory->AddMockHandler(mock_handler.release(),
4463 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484464 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334465
4466 // Add NetLog just so can verify load timing information gets a NetLog ID.
4467 NetLog net_log;
4468 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094469 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334470
4471 // Should try to establish tunnel.
4472 MockWrite data_writes1[] = {
4473 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174474 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334475 "Proxy-Connection: keep-alive\r\n\r\n"),
4476
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"
4480 "Proxy-Authorization: auth_token\r\n\r\n"),
4481 };
4482
4483 // The proxy responds to the connect with a 407, and then hangs up after the
4484 // second request is sent.
4485 MockRead data_reads1[] = {
4486 // No credentials.
4487 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4488 MockRead("Content-Length: 0\r\n"),
4489 MockRead("Proxy-Connection: keep-alive\r\n"),
4490 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4491 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4492 };
4493
4494 // HttpNetworkTransaction sees a reused connection that was closed with
4495 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
4496 // request.
4497 MockWrite data_writes2[] = {
4498 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174499 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334500 "Proxy-Connection: keep-alive\r\n\r\n"),
4501 };
4502
4503 // The proxy, having had more than enough of us, just hangs up.
4504 MockRead data_reads2[] = {
4505 // No credentials.
4506 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4507 };
4508
Ryan Sleevib8d7ea02018-05-07 20:01:014509 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334510 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014511 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334512 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4513
bnc87dcefc2017-05-25 12:47:584514 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194515 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334516
4517 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204518 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014519 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334520
4521 const HttpResponseInfo* response = trans->GetResponseInfo();
4522 ASSERT_TRUE(response);
4523 ASSERT_TRUE(response->headers);
4524 EXPECT_TRUE(response->headers->IsKeepAlive());
4525 EXPECT_EQ(407, response->headers->response_code());
4526 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4527 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584528 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334529
4530 LoadTimingInfo load_timing_info;
4531 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4532
4533 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014534 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:334535
4536 trans.reset();
4537 session->CloseAllConnections();
4538}
4539
Asanka Herathbc3f8f62018-11-16 23:08:304540// This test exercises an odd edge case where the proxy closes the connection
4541// after the authentication handshake is complete. Presumably this technique is
4542// used in lieu of returning a 403 or 5xx status code when the authentication
4543// succeeds, but the user is not authorized to connect to the destination
4544// server. There's no standard for what a proxy should do to indicate a blocked
4545// site.
4546TEST_F(HttpNetworkTransactionTest,
4547 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
4548 HttpRequestInfo request;
4549 request.method = "GET";
4550 request.url = GURL("https://www.example.org/");
4551 request.traffic_annotation =
4552 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4553
4554 // Configure against proxy server "myproxy:70".
4555 session_deps_.proxy_resolution_service =
4556 ProxyResolutionService::CreateFixedFromPacResult(
4557 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4558
Asanka Herathbc3f8f62018-11-16 23:08:304559 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
4560 auth_handler_factory->set_do_init_from_challenge(true);
4561
4562 // Create two mock AuthHandlers. This is because the transaction gets retried
4563 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
4564 // was a real network error.
4565 //
4566 // The handlers support both default and explicit credentials. The retry
4567 // mentioned above should be able to reuse the default identity. Thus there
4568 // should never be a need to prompt for explicit credentials.
4569 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
4570 mock_handler->set_allows_default_credentials(true);
4571 mock_handler->set_allows_explicit_credentials(true);
4572 mock_handler->set_connection_based(true);
4573 auth_handler_factory->AddMockHandler(mock_handler.release(),
4574 HttpAuth::AUTH_PROXY);
4575 mock_handler = std::make_unique<HttpAuthHandlerMock>();
4576 mock_handler->set_allows_default_credentials(true);
4577 mock_handler->set_allows_explicit_credentials(true);
4578 mock_handler->set_connection_based(true);
4579 auth_handler_factory->AddMockHandler(mock_handler.release(),
4580 HttpAuth::AUTH_PROXY);
4581 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4582
4583 NetLog net_log;
4584 session_deps_.net_log = &net_log;
4585 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4586
4587 // Data for both sockets.
4588 //
4589 // Writes are for the tunnel establishment attempts and the
4590 // authentication handshake.
4591 MockWrite data_writes1[] = {
4592 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4593 "Host: www.example.org:443\r\n"
4594 "Proxy-Connection: keep-alive\r\n\r\n"),
4595
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"
4599 "Proxy-Authorization: auth_token\r\n\r\n"),
4600
4601 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4602 "Host: www.example.org:443\r\n"
4603 "Proxy-Connection: keep-alive\r\n"
4604 "Proxy-Authorization: auth_token\r\n\r\n"),
4605 };
4606
4607 // The server side of the authentication handshake. Note that the response to
4608 // the final CONNECT request is ERR_CONNECTION_CLOSED.
4609 MockRead data_reads1[] = {
4610 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4611 MockRead("Content-Length: 0\r\n"),
4612 MockRead("Proxy-Connection: keep-alive\r\n"),
4613 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
4614
4615 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4616 MockRead("Content-Length: 0\r\n"),
4617 MockRead("Proxy-Connection: keep-alive\r\n"),
4618 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
4619
4620 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
4621 };
4622
4623 StaticSocketDataProvider data1(data_reads1, data_writes1);
4624 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4625
4626 // The second socket is for the reconnection attempt. Data is identical to the
4627 // first attempt.
4628 StaticSocketDataProvider data2(data_reads1, data_writes1);
4629 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4630
4631 auto trans =
4632 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4633
4634 TestCompletionCallback callback;
4635 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4636
4637 // Two rounds per handshake. After one retry, the error is propagated up the
4638 // stack.
4639 for (int i = 0; i < 4; ++i) {
4640 EXPECT_THAT(callback.GetResult(rv), IsOk());
4641
4642 const HttpResponseInfo* response = trans->GetResponseInfo();
4643 ASSERT_TRUE(response);
4644 ASSERT_TRUE(response->headers);
4645 EXPECT_EQ(407, response->headers->response_code());
4646 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
4647
4648 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4649 }
4650
4651 // One shall be the number thou shalt retry, and the number of the retrying
4652 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
4653 // that thou then proceed to one. Three is right out. Once the number one,
4654 // being the first number, be reached, then lobbest thou thy
4655 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
4656 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
4657
4658 trans.reset();
4659 session->CloseAllConnections();
4660}
4661
mmenke2a1781d2015-10-07 19:25:334662// Test a proxy auth scheme that allows default credentials and a proxy server
4663// that hangs up when credentials are initially sent, and sends a challenge
4664// again they are retried.
bncd16676a2016-07-20 16:23:014665TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:334666 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
4667 HttpRequestInfo request;
4668 request.method = "GET";
4669 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104670 request.traffic_annotation =
4671 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334672
4673 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:594674 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:494675 ProxyResolutionService::CreateFixedFromPacResult(
4676 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
mmenke2a1781d2015-10-07 19:25:334677
Jeremy Roman0579ed62017-08-29 15:56:194678 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
mmenke2a1781d2015-10-07 19:25:334679 auth_handler_factory->set_do_init_from_challenge(true);
Jeremy Roman0579ed62017-08-29 15:56:194680 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334681 mock_handler->set_allows_default_credentials(true);
4682 auth_handler_factory->AddMockHandler(mock_handler.release(),
4683 HttpAuth::AUTH_PROXY);
4684 // Add another handler for the second challenge. It supports default
4685 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194686 mock_handler = std::make_unique<HttpAuthHandlerMock>();
mmenke2a1781d2015-10-07 19:25:334687 mock_handler->set_allows_default_credentials(true);
4688 auth_handler_factory->AddMockHandler(mock_handler.release(),
4689 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484690 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334691
4692 // Add NetLog just so can verify load timing information gets a NetLog ID.
4693 NetLog net_log;
4694 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094695 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334696
4697 // Should try to establish tunnel.
4698 MockWrite data_writes1[] = {
4699 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174700 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334701 "Proxy-Connection: keep-alive\r\n\r\n"),
4702 };
4703
4704 // The proxy responds to the connect with a 407, using a non-persistent
4705 // connection.
4706 MockRead data_reads1[] = {
4707 // No credentials.
4708 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4709 MockRead("Proxy-Authenticate: Mock\r\n"),
4710 MockRead("Proxy-Connection: close\r\n\r\n"),
4711 };
4712
4713 // Since the first connection was closed, need to establish another once given
4714 // credentials.
4715 MockWrite data_writes2[] = {
4716 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174717 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334718 "Proxy-Connection: keep-alive\r\n"
4719 "Proxy-Authorization: auth_token\r\n\r\n"),
4720 };
4721
4722 MockRead data_reads2[] = {
4723 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4724 MockRead("Proxy-Authenticate: Mock\r\n"),
4725 MockRead("Proxy-Connection: close\r\n\r\n"),
4726 };
4727
Ryan Sleevib8d7ea02018-05-07 20:01:014728 StaticSocketDataProvider data1(data_reads1, data_writes1);
mmenke2a1781d2015-10-07 19:25:334729 session_deps_.socket_factory->AddSocketDataProvider(&data1);
Ryan Sleevib8d7ea02018-05-07 20:01:014730 StaticSocketDataProvider data2(data_reads2, data_writes2);
mmenke2a1781d2015-10-07 19:25:334731 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4732 SSLSocketDataProvider ssl(ASYNC, OK);
4733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4734
bnc87dcefc2017-05-25 12:47:584735 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194736 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
mmenke2a1781d2015-10-07 19:25:334737
4738 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:204739 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:014740 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334741
4742 const HttpResponseInfo* response = trans->GetResponseInfo();
4743 ASSERT_TRUE(response);
4744 ASSERT_TRUE(response->headers);
4745 EXPECT_EQ(407, response->headers->response_code());
4746 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4747 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584748 EXPECT_FALSE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334749
4750 LoadTimingInfo load_timing_info;
4751 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4752
4753 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014754 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334755 response = trans->GetResponseInfo();
4756 ASSERT_TRUE(response);
4757 ASSERT_TRUE(response->headers);
4758 EXPECT_EQ(407, response->headers->response_code());
4759 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584760 EXPECT_TRUE(response->auth_challenge.has_value());
mmenke2a1781d2015-10-07 19:25:334761
4762 trans.reset();
4763 session->CloseAllConnections();
4764}
4765
asankae2257db2016-10-11 22:03:164766// A more nuanced test than GenerateAuthToken test which asserts that
4767// ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
4768// unnecessarily invalidated, and that if the server co-operates, the
4769// authentication handshake can continue with the same scheme but with a
4770// different identity.
4771TEST_F(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
4772 HttpRequestInfo request;
4773 request.method = "GET";
4774 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:104775 request.traffic_annotation =
4776 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
asankae2257db2016-10-11 22:03:164777
Jeremy Roman0579ed62017-08-29 15:56:194778 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
asankae2257db2016-10-11 22:03:164779 auth_handler_factory->set_do_init_from_challenge(true);
4780
4781 // First handler. Uses default credentials, but barfs at generate auth token.
Jeremy Roman0579ed62017-08-29 15:56:194782 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164783 mock_handler->set_allows_default_credentials(true);
4784 mock_handler->set_allows_explicit_credentials(true);
4785 mock_handler->set_connection_based(true);
4786 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
4787 auth_handler_factory->AddMockHandler(mock_handler.release(),
4788 HttpAuth::AUTH_SERVER);
4789
4790 // Add another handler for the second challenge. It supports default
4791 // credentials, but they shouldn't be used, since they were already tried.
Jeremy Roman0579ed62017-08-29 15:56:194792 mock_handler = std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:164793 mock_handler->set_allows_default_credentials(true);
4794 mock_handler->set_allows_explicit_credentials(true);
4795 mock_handler->set_connection_based(true);
4796 auth_handler_factory->AddMockHandler(mock_handler.release(),
4797 HttpAuth::AUTH_SERVER);
4798 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
4799
4800 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4801
4802 MockWrite data_writes1[] = {
4803 MockWrite("GET / HTTP/1.1\r\n"
4804 "Host: www.example.org\r\n"
4805 "Connection: keep-alive\r\n\r\n"),
4806 };
4807
4808 MockRead data_reads1[] = {
4809 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4810 "WWW-Authenticate: Mock\r\n"
4811 "Connection: keep-alive\r\n\r\n"),
4812 };
4813
4814 // Identical to data_writes1[]. The AuthHandler encounters a
4815 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
4816 // transaction procceds without an authorization header.
4817 MockWrite data_writes2[] = {
4818 MockWrite("GET / HTTP/1.1\r\n"
4819 "Host: www.example.org\r\n"
4820 "Connection: keep-alive\r\n\r\n"),
4821 };
4822
4823 MockRead data_reads2[] = {
4824 MockRead("HTTP/1.1 401 Authentication Required\r\n"
4825 "WWW-Authenticate: Mock\r\n"
4826 "Connection: keep-alive\r\n\r\n"),
4827 };
4828
4829 MockWrite data_writes3[] = {
4830 MockWrite("GET / HTTP/1.1\r\n"
4831 "Host: www.example.org\r\n"
4832 "Connection: keep-alive\r\n"
4833 "Authorization: auth_token\r\n\r\n"),
4834 };
4835
4836 MockRead data_reads3[] = {
4837 MockRead("HTTP/1.1 200 OK\r\n"
4838 "Content-Length: 5\r\n"
4839 "Content-Type: text/plain\r\n"
4840 "Connection: keep-alive\r\n\r\n"
4841 "Hello"),
4842 };
4843
Ryan Sleevib8d7ea02018-05-07 20:01:014844 StaticSocketDataProvider data1(data_reads1, data_writes1);
asankae2257db2016-10-11 22:03:164845 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4846
Ryan Sleevib8d7ea02018-05-07 20:01:014847 StaticSocketDataProvider data2(data_reads2, data_writes2);
asankae2257db2016-10-11 22:03:164848 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4849
Ryan Sleevib8d7ea02018-05-07 20:01:014850 StaticSocketDataProvider data3(data_reads3, data_writes3);
asankae2257db2016-10-11 22:03:164851 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4852
bnc87dcefc2017-05-25 12:47:584853 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:194854 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
asankae2257db2016-10-11 22:03:164855
4856 TestCompletionCallback callback;
4857 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
4858 EXPECT_THAT(callback.GetResult(rv), IsOk());
4859
4860 const HttpResponseInfo* response = trans->GetResponseInfo();
4861 ASSERT_TRUE(response);
4862 ASSERT_TRUE(response->headers);
4863 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4864
4865 // The following three tests assert that an authentication challenge was
4866 // received and that the stack is ready to respond to the challenge using
4867 // ambient credentials.
4868 EXPECT_EQ(401, response->headers->response_code());
4869 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584870 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164871
4872 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4873 EXPECT_THAT(callback.GetResult(rv), IsOk());
4874 response = trans->GetResponseInfo();
4875 ASSERT_TRUE(response);
4876 ASSERT_TRUE(response->headers);
4877
4878 // The following three tests assert that an authentication challenge was
4879 // received and that the stack needs explicit credentials before it is ready
4880 // to respond to the challenge.
4881 EXPECT_EQ(401, response->headers->response_code());
4882 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
Emily Starkf2c9bbd2019-04-09 17:08:584883 EXPECT_TRUE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:164884
4885 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
4886 EXPECT_THAT(callback.GetResult(rv), IsOk());
4887 response = trans->GetResponseInfo();
4888 ASSERT_TRUE(response);
4889 ASSERT_TRUE(response->headers);
4890 EXPECT_EQ(200, response->headers->response_code());
4891
4892 trans.reset();
4893 session->CloseAllConnections();
4894}
4895
Matt Menked1eb6d42018-01-17 04:54:064896// Proxy resolver that returns a proxy with the same host and port for different
4897// schemes, based on the path of the URL being requests.
4898class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
4899 public:
4900 SameProxyWithDifferentSchemesProxyResolver() {}
4901 ~SameProxyWithDifferentSchemesProxyResolver() override {}
4902
4903 static std::string ProxyHostPortPairAsString() { return "proxy.test:10000"; }
4904
4905 static HostPortPair ProxyHostPortPair() {
4906 return HostPortPair::FromString(ProxyHostPortPairAsString());
4907 }
4908
4909 // ProxyResolver implementation.
4910 int GetProxyForURL(const GURL& url,
4911 ProxyInfo* results,
Bence Békycc5b88a2018-05-25 20:24:174912 CompletionOnceCallback callback,
Matt Menked1eb6d42018-01-17 04:54:064913 std::unique_ptr<Request>* request,
4914 const NetLogWithSource& /*net_log*/) override {
4915 *results = ProxyInfo();
Ramin Halavati921731ea2018-03-16 08:24:574916 results->set_traffic_annotation(
4917 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
Matt Menked1eb6d42018-01-17 04:54:064918 if (url.path() == "/socks4") {
4919 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
4920 return OK;
4921 }
4922 if (url.path() == "/socks5") {
4923 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
4924 return OK;
4925 }
4926 if (url.path() == "/http") {
4927 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
4928 return OK;
4929 }
4930 if (url.path() == "/https") {
4931 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
4932 return OK;
4933 }
Matt Menkee8648fa2019-01-17 16:47:074934 if (url.path() == "/https_trusted") {
4935 results->UseProxyServer(ProxyServer(ProxyServer::SCHEME_HTTPS,
4936 ProxyHostPortPair(),
4937 true /* is_trusted_proxy */));
4938 return OK;
4939 }
Matt Menked1eb6d42018-01-17 04:54:064940 NOTREACHED();
4941 return ERR_NOT_IMPLEMENTED;
4942 }
4943
4944 private:
4945 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolver);
4946};
4947
4948class SameProxyWithDifferentSchemesProxyResolverFactory
4949 : public ProxyResolverFactory {
4950 public:
4951 SameProxyWithDifferentSchemesProxyResolverFactory()
4952 : ProxyResolverFactory(false) {}
4953
Lily Houghton99597862018-03-07 16:40:424954 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
4955 std::unique_ptr<ProxyResolver>* resolver,
Bence Békycc5b88a2018-05-25 20:24:174956 CompletionOnceCallback callback,
Lily Houghton99597862018-03-07 16:40:424957 std::unique_ptr<Request>* request) override {
Matt Menked1eb6d42018-01-17 04:54:064958 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
4959 return OK;
4960 }
4961
4962 private:
4963 DISALLOW_COPY_AND_ASSIGN(SameProxyWithDifferentSchemesProxyResolverFactory);
4964};
4965
4966// Check that when different proxy schemes are all applied to a proxy at the
Matt Menkee8648fa2019-01-17 16:47:074967// same address, the connections are not grouped together. i.e., a request to
Matt Menked1eb6d42018-01-17 04:54:064968// foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
4969// request to foo.com using proxy.com as an HTTP proxy.
4970TEST_F(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
Ramin Halavatica8d5252018-03-12 05:33:494971 session_deps_.proxy_resolution_service =
4972 std::make_unique<ProxyResolutionService>(
4973 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
4974 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
4975 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
4976 nullptr);
Matt Menked1eb6d42018-01-17 04:54:064977
4978 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4979
4980 MockWrite socks_writes[] = {
4981 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
4982 kSOCKS4OkRequestLocalHostPort80Length),
4983 MockWrite(SYNCHRONOUS,
4984 "GET /socks4 HTTP/1.1\r\n"
4985 "Host: test\r\n"
4986 "Connection: keep-alive\r\n\r\n"),
4987 };
4988 MockRead socks_reads[] = {
4989 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
4990 MockRead("HTTP/1.0 200 OK\r\n"
4991 "Connection: keep-alive\r\n"
4992 "Content-Length: 15\r\n\r\n"
4993 "SOCKS4 Response"),
4994 };
Ryan Sleevib8d7ea02018-05-07 20:01:014995 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
Matt Menked1eb6d42018-01-17 04:54:064996 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
4997
4998 const char kSOCKS5Request[] = {
4999 0x05, // Version
5000 0x01, // Command (CONNECT)
5001 0x00, // Reserved
5002 0x03, // Address type (DOMAINNAME)
5003 0x04, // Length of domain (4)
5004 't', 'e', 's', 't', // Domain string
5005 0x00, 0x50, // 16-bit port (80)
5006 };
5007 MockWrite socks5_writes[] = {
5008 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Avi Drissman4365a4782018-12-28 19:26:245009 MockWrite(ASYNC, kSOCKS5Request, base::size(kSOCKS5Request)),
Matt Menked1eb6d42018-01-17 04:54:065010 MockWrite(SYNCHRONOUS,
5011 "GET /socks5 HTTP/1.1\r\n"
5012 "Host: test\r\n"
5013 "Connection: keep-alive\r\n\r\n"),
5014 };
5015 MockRead socks5_reads[] = {
5016 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
5017 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
5018 MockRead("HTTP/1.0 200 OK\r\n"
5019 "Connection: keep-alive\r\n"
5020 "Content-Length: 15\r\n\r\n"
5021 "SOCKS5 Response"),
5022 };
Ryan Sleevib8d7ea02018-05-07 20:01:015023 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
Matt Menked1eb6d42018-01-17 04:54:065024 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
5025
5026 MockWrite http_writes[] = {
5027 MockWrite(SYNCHRONOUS,
5028 "GET http://test/http HTTP/1.1\r\n"
5029 "Host: test\r\n"
5030 "Proxy-Connection: keep-alive\r\n\r\n"),
5031 };
5032 MockRead http_reads[] = {
5033 MockRead("HTTP/1.1 200 OK\r\n"
5034 "Proxy-Connection: keep-alive\r\n"
5035 "Content-Length: 13\r\n\r\n"
5036 "HTTP Response"),
5037 };
Ryan Sleevib8d7ea02018-05-07 20:01:015038 StaticSocketDataProvider http_data(http_reads, http_writes);
Matt Menked1eb6d42018-01-17 04:54:065039 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
5040
5041 MockWrite https_writes[] = {
5042 MockWrite(SYNCHRONOUS,
5043 "GET http://test/https HTTP/1.1\r\n"
5044 "Host: test\r\n"
5045 "Proxy-Connection: keep-alive\r\n\r\n"),
5046 };
5047 MockRead https_reads[] = {
5048 MockRead("HTTP/1.1 200 OK\r\n"
5049 "Proxy-Connection: keep-alive\r\n"
5050 "Content-Length: 14\r\n\r\n"
5051 "HTTPS Response"),
5052 };
Ryan Sleevib8d7ea02018-05-07 20:01:015053 StaticSocketDataProvider https_data(https_reads, https_writes);
Matt Menked1eb6d42018-01-17 04:54:065054 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
5055 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
5056 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5057
Matt Menkee8648fa2019-01-17 16:47:075058 MockWrite https_trusted_writes[] = {
5059 MockWrite(SYNCHRONOUS,
5060 "GET http://test/https_trusted HTTP/1.1\r\n"
5061 "Host: test\r\n"
5062 "Proxy-Connection: keep-alive\r\n\r\n"),
5063 };
5064 MockRead https_trusted_reads[] = {
5065 MockRead("HTTP/1.1 200 OK\r\n"
5066 "Proxy-Connection: keep-alive\r\n"
5067 "Content-Length: 22\r\n\r\n"
5068 "HTTPS Trusted Response"),
5069 };
5070 StaticSocketDataProvider trusted_https_data(https_trusted_reads,
5071 https_trusted_writes);
5072 session_deps_.socket_factory->AddSocketDataProvider(&trusted_https_data);
5073 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
5074 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
5075
Matt Menked1eb6d42018-01-17 04:54:065076 struct TestCase {
5077 GURL url;
5078 std::string expected_response;
Matt Menkee8648fa2019-01-17 16:47:075079 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
Matt Menked1eb6d42018-01-17 04:54:065080 // after the test.
Matt Menkee8648fa2019-01-17 16:47:075081 int expected_idle_socks4_sockets;
5082 int expected_idle_socks5_sockets;
5083 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
5084 // pools after the test.
Matt Menked1eb6d42018-01-17 04:54:065085 int expected_idle_http_sockets;
Matt Menkee8648fa2019-01-17 16:47:075086 int expected_idle_https_sockets;
5087 // How many idle sockets there should be in the HTTPS proxy socket pool with
5088 // the ProxyServer's |is_trusted_proxy| bit set after the test.
5089 int expected_idle_trusted_https_sockets;
Matt Menked1eb6d42018-01-17 04:54:065090 } const kTestCases[] = {
Matt Menkee8648fa2019-01-17 16:47:075091 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0, 0},
5092 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0, 0},
5093 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0, 0},
5094 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1, 0},
5095 {GURL("http://test/https_trusted"), "HTTPS Trusted Response", 1, 1, 1, 1,
5096 1},
Matt Menked1eb6d42018-01-17 04:54:065097 };
5098
5099 for (const auto& test_case : kTestCases) {
5100 HttpRequestInfo request;
5101 request.method = "GET";
5102 request.url = test_case.url;
Ramin Halavatib5e433e62018-02-07 07:41:105103 request.traffic_annotation =
5104 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menked1eb6d42018-01-17 04:54:065105 std::unique_ptr<HttpNetworkTransaction> trans =
5106 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
5107 session.get());
5108 TestCompletionCallback callback;
5109 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5110 EXPECT_THAT(callback.GetResult(rv), IsOk());
5111
5112 const HttpResponseInfo* response = trans->GetResponseInfo();
5113 ASSERT_TRUE(response);
5114 ASSERT_TRUE(response->headers);
5115 EXPECT_EQ(200, response->headers->response_code());
5116 std::string response_data;
5117 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5118 EXPECT_EQ(test_case.expected_response, response_data);
5119
5120 // Return the socket to the socket pool, so can make sure it's not used for
5121 // the next requests.
5122 trans.reset();
5123 base::RunLoop().RunUntilIdle();
5124
5125 // Check the number of idle sockets in the pool, to make sure that used
5126 // sockets are indeed being returned to the socket pool. If each request
5127 // doesn't return an idle socket to the pool, the test would incorrectly
5128 // pass.
Matt Menkee8648fa2019-01-17 16:47:075129 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
5130 session
Matt Menked23ab952019-03-06 00:24:405131 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075132 HttpNetworkSession::NORMAL_SOCKET_POOL,
5133 ProxyServer(ProxyServer::SCHEME_SOCKS4,
5134 SameProxyWithDifferentSchemesProxyResolver::
5135 ProxyHostPortPair()))
5136 ->IdleSocketCount());
5137 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
5138 session
Matt Menked23ab952019-03-06 00:24:405139 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075140 HttpNetworkSession::NORMAL_SOCKET_POOL,
5141 ProxyServer(ProxyServer::SCHEME_SOCKS5,
5142 SameProxyWithDifferentSchemesProxyResolver::
5143 ProxyHostPortPair()))
5144 ->IdleSocketCount());
5145 EXPECT_EQ(test_case.expected_idle_http_sockets,
5146 session
Matt Menked23ab952019-03-06 00:24:405147 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075148 HttpNetworkSession::NORMAL_SOCKET_POOL,
5149 ProxyServer(ProxyServer::SCHEME_HTTP,
5150 SameProxyWithDifferentSchemesProxyResolver::
5151 ProxyHostPortPair()))
5152 ->IdleSocketCount());
5153 EXPECT_EQ(test_case.expected_idle_https_sockets,
5154 session
Matt Menked23ab952019-03-06 00:24:405155 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075156 HttpNetworkSession::NORMAL_SOCKET_POOL,
5157 ProxyServer(ProxyServer::SCHEME_HTTPS,
5158 SameProxyWithDifferentSchemesProxyResolver::
5159 ProxyHostPortPair()))
5160 ->IdleSocketCount());
5161 EXPECT_EQ(test_case.expected_idle_trusted_https_sockets,
5162 session
Matt Menked23ab952019-03-06 00:24:405163 ->GetSocketPool(
Matt Menkee8648fa2019-01-17 16:47:075164 HttpNetworkSession::NORMAL_SOCKET_POOL,
5165 ProxyServer(ProxyServer::SCHEME_HTTPS,
5166 SameProxyWithDifferentSchemesProxyResolver::
5167 ProxyHostPortPair(),
5168 true /* is_trusted_proxy */))
5169 ->IdleSocketCount());
Matt Menked1eb6d42018-01-17 04:54:065170 }
5171}
5172
[email protected]029c83b62013-01-24 05:28:205173// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:015174TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205175 HttpRequestInfo request1;
5176 request1.method = "GET";
bncce36dca22015-04-21 22:11:235177 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105178 request1.traffic_annotation =
5179 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205180
5181 HttpRequestInfo request2;
5182 request2.method = "GET";
bncce36dca22015-04-21 22:11:235183 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105184 request2.traffic_annotation =
5185 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205186
5187 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495188 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5189 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515190 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075191 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095192 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205193
5194 // Since we have proxy, should try to establish tunnel.
5195 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175196 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5197 "Host: www.example.org:443\r\n"
5198 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205199
rsleevidb16bb02015-11-12 23:47:175200 MockWrite("GET /1 HTTP/1.1\r\n"
5201 "Host: www.example.org\r\n"
5202 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205203
rsleevidb16bb02015-11-12 23:47:175204 MockWrite("GET /2 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 };
5208
5209 // The proxy responds to the connect with a 407, using a persistent
5210 // connection.
5211 MockRead data_reads1[] = {
5212 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5213
5214 MockRead("HTTP/1.1 200 OK\r\n"),
5215 MockRead("Content-Length: 1\r\n\r\n"),
5216 MockRead(SYNCHRONOUS, "1"),
5217
5218 MockRead("HTTP/1.1 200 OK\r\n"),
5219 MockRead("Content-Length: 2\r\n\r\n"),
5220 MockRead(SYNCHRONOUS, "22"),
5221 };
5222
Ryan Sleevib8d7ea02018-05-07 20:01:015223 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075224 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205225 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075226 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205227
5228 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585229 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195230 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205231
5232 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015233 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205234
5235 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015236 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205237
5238 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525239 ASSERT_TRUE(response1);
tbansal2ecbbc72016-10-06 17:15:475240 EXPECT_TRUE(response1->proxy_server.is_http());
wezca1070932016-05-26 20:30:525241 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205242 EXPECT_EQ(1, response1->headers->GetContentLength());
5243
5244 LoadTimingInfo load_timing_info1;
5245 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5246 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
5247
5248 trans1.reset();
5249
5250 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585251 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195252 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205253
5254 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015255 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205256
5257 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015258 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205259
5260 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525261 ASSERT_TRUE(response2);
tbansal2ecbbc72016-10-06 17:15:475262 EXPECT_TRUE(response2->proxy_server.is_http());
wezca1070932016-05-26 20:30:525263 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205264 EXPECT_EQ(2, response2->headers->GetContentLength());
5265
5266 LoadTimingInfo load_timing_info2;
5267 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5268 TestLoadTimingReused(load_timing_info2);
5269
5270 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5271
5272 trans2.reset();
5273 session->CloseAllConnections();
5274}
5275
5276// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:015277TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:205278 HttpRequestInfo request1;
5279 request1.method = "GET";
bncce36dca22015-04-21 22:11:235280 request1.url = GURL("https://www.example.org/1");
Ramin Halavatib5e433e62018-02-07 07:41:105281 request1.traffic_annotation =
5282 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205283
5284 HttpRequestInfo request2;
5285 request2.method = "GET";
bncce36dca22015-04-21 22:11:235286 request2.url = GURL("https://www.example.org/2");
Ramin Halavatib5e433e62018-02-07 07:41:105287 request2.traffic_annotation =
5288 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:205289
5290 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:595291 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:495292 ProxyResolutionService::CreateFixedFromPacResult(
5293 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515294 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075295 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095296 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:205297
5298 // Since we have proxy, should try to establish tunnel.
5299 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175300 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5301 "Host: www.example.org:443\r\n"
5302 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205303
rsleevidb16bb02015-11-12 23:47:175304 MockWrite("GET /1 HTTP/1.1\r\n"
5305 "Host: www.example.org\r\n"
5306 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:205307
rsleevidb16bb02015-11-12 23:47:175308 MockWrite("GET /2 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 };
5312
5313 // The proxy responds to the connect with a 407, using a persistent
5314 // connection.
5315 MockRead data_reads1[] = {
5316 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5317
5318 MockRead("HTTP/1.1 200 OK\r\n"),
5319 MockRead("Content-Length: 1\r\n\r\n"),
5320 MockRead(SYNCHRONOUS, "1"),
5321
5322 MockRead("HTTP/1.1 200 OK\r\n"),
5323 MockRead("Content-Length: 2\r\n\r\n"),
5324 MockRead(SYNCHRONOUS, "22"),
5325 };
5326
Ryan Sleevib8d7ea02018-05-07 20:01:015327 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075328 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:205329 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:205331
5332 TestCompletionCallback callback1;
bnc87dcefc2017-05-25 12:47:585333 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:195334 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205335
5336 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015337 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205338
5339 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015340 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205341
5342 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:525343 ASSERT_TRUE(response1);
5344 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:205345 EXPECT_EQ(1, response1->headers->GetContentLength());
5346
5347 LoadTimingInfo load_timing_info1;
5348 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
5349 TestLoadTimingNotReusedWithPac(load_timing_info1,
5350 CONNECT_TIMING_HAS_SSL_TIMES);
5351
5352 trans1.reset();
5353
5354 TestCompletionCallback callback2;
bnc87dcefc2017-05-25 12:47:585355 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:195356 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:205357
5358 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015359 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:205360
5361 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015362 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:205363
5364 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:525365 ASSERT_TRUE(response2);
5366 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:205367 EXPECT_EQ(2, response2->headers->GetContentLength());
5368
5369 LoadTimingInfo load_timing_info2;
5370 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5371 TestLoadTimingReusedWithPac(load_timing_info2);
5372
5373 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
5374
5375 trans2.reset();
5376 session->CloseAllConnections();
5377}
5378
[email protected]2df19bb2010-08-25 20:13:465379// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015380TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275381 HttpRequestInfo request;
5382 request.method = "GET";
bncce36dca22015-04-21 22:11:235383 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105384 request.traffic_annotation =
5385 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275386
[email protected]2df19bb2010-08-25 20:13:465387 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495388 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5389 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515390 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075391 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095392 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:465393
[email protected]2df19bb2010-08-25 20:13:465394 // Since we have proxy, should use full url
5395 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235396 MockWrite(
5397 "GET http://www.example.org/ HTTP/1.1\r\n"
5398 "Host: www.example.org\r\n"
5399 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465400 };
5401
5402 MockRead data_reads1[] = {
5403 MockRead("HTTP/1.1 200 OK\r\n"),
5404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5405 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065406 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465407 };
5408
Ryan Sleevib8d7ea02018-05-07 20:01:015409 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:075410 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065411 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075412 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465413
[email protected]49639fa2011-12-20 23:22:415414 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465415
bnc691fda62016-08-12 00:43:165416 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505417
bnc691fda62016-08-12 00:43:165418 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015419 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465420
5421 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015422 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465423
[email protected]58e32bb2013-01-21 18:23:255424 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165425 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255426 TestLoadTimingNotReused(load_timing_info,
5427 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5428
bnc691fda62016-08-12 00:43:165429 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525430 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465431
tbansal2ecbbc72016-10-06 17:15:475432 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:465433 EXPECT_TRUE(response->headers->IsKeepAlive());
5434 EXPECT_EQ(200, response->headers->response_code());
5435 EXPECT_EQ(100, response->headers->GetContentLength());
5436 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5437
5438 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585439 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:465440}
5441
[email protected]7642b5ae2010-09-01 20:55:175442// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015443TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:275444 HttpRequestInfo request;
5445 request.method = "GET";
bncce36dca22015-04-21 22:11:235446 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105447 request.traffic_annotation =
5448 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275449
[email protected]7642b5ae2010-09-01 20:55:175450 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495451 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5452 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515453 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075454 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095455 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:175456
bncce36dca22015-04-21 22:11:235457 // fetch http://www.example.org/ via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135458 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455459 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415460 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:175461
Ryan Hamilton0239aac2018-05-19 00:03:135462 spdy::SpdySerializedFrame resp(
5463 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
5464 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:175465 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415466 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:175467 };
5468
Ryan Sleevib8d7ea02018-05-07 20:01:015469 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075470 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:175471
[email protected]8ddf8322012-02-23 18:08:065472 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365473 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075474 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:175475
[email protected]49639fa2011-12-20 23:22:415476 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:175477
bnc691fda62016-08-12 00:43:165478 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:505479
bnc691fda62016-08-12 00:43:165480 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015481 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:175482
5483 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015484 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:175485
[email protected]58e32bb2013-01-21 18:23:255486 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165487 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255488 TestLoadTimingNotReused(load_timing_info,
5489 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5490
bnc691fda62016-08-12 00:43:165491 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525492 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:475493 EXPECT_TRUE(response->proxy_server.is_https());
wezca1070932016-05-26 20:30:525494 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025495 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:175496
5497 std::string response_data;
bnc691fda62016-08-12 00:43:165498 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235499 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:175500}
5501
[email protected]1c173852014-06-19 12:51:505502// Verifies that a session which races and wins against the owning transaction
5503// (completing prior to host resolution), doesn't fail the transaction.
5504// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:015505TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:505506 HttpRequestInfo request;
5507 request.method = "GET";
bncce36dca22015-04-21 22:11:235508 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105509 request.traffic_annotation =
5510 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c173852014-06-19 12:51:505511
5512 // Configure SPDY proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495513 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5514 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515515 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:505516 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095517 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:505518
bncce36dca22015-04-21 22:11:235519 // Fetch http://www.example.org/ through the SPDY proxy.
Ryan Hamilton0239aac2018-05-19 00:03:135520 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:455521 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:415522 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:505523
Raul Tambre94493c652019-03-11 17:18:355524 spdy::SpdySerializedFrame resp(
5525 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135526 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:505527 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415528 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:505529 };
5530
Ryan Sleevib8d7ea02018-05-07 20:01:015531 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]1c173852014-06-19 12:51:505532 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5533
5534 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365535 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:505536 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5537
5538 TestCompletionCallback callback1;
5539
bnc691fda62016-08-12 00:43:165540 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]1c173852014-06-19 12:51:505541
5542 // Stall the hostname resolution begun by the transaction.
[email protected]1c173852014-06-19 12:51:505543 session_deps_.host_resolver->set_ondemand_mode(true);
5544
bnc691fda62016-08-12 00:43:165545 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015546 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:505547
5548 // Race a session to the proxy, which completes first.
5549 session_deps_.host_resolver->set_ondemand_mode(false);
Paul Jensena457017a2018-01-19 23:52:045550 SpdySessionKey key(HostPortPair("proxy", 70), ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:115551 PRIVACY_MODE_DISABLED,
5552 SpdySessionKey::IsProxySession::kTrue, SocketTag());
[email protected]1c173852014-06-19 12:51:505553 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:525554 CreateSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:505555
5556 // Unstall the resolution begun by the transaction.
5557 session_deps_.host_resolver->set_ondemand_mode(true);
5558 session_deps_.host_resolver->ResolveAllPending();
5559
5560 EXPECT_FALSE(callback1.have_result());
5561 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015562 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:505563
bnc691fda62016-08-12 00:43:165564 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525565 ASSERT_TRUE(response);
5566 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025567 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:505568
5569 std::string response_data;
bnc691fda62016-08-12 00:43:165570 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:505571 EXPECT_EQ(kUploadData, response_data);
5572}
5573
[email protected]dc7bd1c52010-11-12 00:01:135574// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015575TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:275576 HttpRequestInfo request;
5577 request.method = "GET";
bncce36dca22015-04-21 22:11:235578 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105579 request.traffic_annotation =
5580 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275581
[email protected]79cb5c12011-09-12 13:12:045582 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495583 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5584 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515585 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075586 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095587 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:135588
[email protected]dc7bd1c52010-11-12 00:01:135589 // The first request will be a bare GET, the second request will be a
5590 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:455591 spdy_util_.set_default_url(request.url);
Ryan Hamilton0239aac2018-05-19 00:03:135592 spdy::SpdySerializedFrame req_get(
Bence Béky27ad0a12018-02-08 00:35:485593 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:385594 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:135595 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465596 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:135597 };
Ryan Hamilton0239aac2018-05-19 00:03:135598 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
Avi Drissman4365a4782018-12-28 19:26:245599 kExtraAuthorizationHeaders, base::size(kExtraAuthorizationHeaders) / 2, 3,
Bence Béky27ad0a12018-02-08 00:35:485600 LOWEST));
[email protected]dc7bd1c52010-11-12 00:01:135601 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415602 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:135603 };
5604
5605 // The first response is a 407 proxy authentication challenge, and the second
5606 // response will be a 200 response since the second request includes a valid
5607 // Authorization header.
5608 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:465609 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:135610 };
Ryan Hamilton0239aac2018-05-19 00:03:135611 spdy::SpdySerializedFrame resp_authentication(
5612 spdy_util_.ConstructSpdyReplyError(
5613 "407", kExtraAuthenticationHeaders,
Avi Drissman4365a4782018-12-28 19:26:245614 base::size(kExtraAuthenticationHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135615 spdy::SpdySerializedFrame body_authentication(
bncdf80d44fd2016-07-15 20:27:415616 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:135617 spdy::SpdySerializedFrame resp_data(
Raul Tambre94493c652019-03-11 17:18:355618 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:135619 spdy::SpdySerializedFrame body_data(
5620 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:135621 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415622 CreateMockRead(resp_authentication, 1),
bnceb9aa7112017-01-05 01:03:465623 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:415624 CreateMockRead(resp_data, 4),
5625 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:135626 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:135627 };
5628
Ryan Sleevib8d7ea02018-05-07 20:01:015629 SequencedSocketData data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075630 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:135631
[email protected]8ddf8322012-02-23 18:08:065632 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365633 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075634 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:135635
[email protected]49639fa2011-12-20 23:22:415636 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:135637
bnc691fda62016-08-12 00:43:165638 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]dc7bd1c52010-11-12 00:01:135639
bnc691fda62016-08-12 00:43:165640 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015641 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135642
5643 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015644 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135645
bnc691fda62016-08-12 00:43:165646 const HttpResponseInfo* const response = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135647
wezca1070932016-05-26 20:30:525648 ASSERT_TRUE(response);
5649 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:135650 EXPECT_EQ(407, response->headers->response_code());
5651 EXPECT_TRUE(response->was_fetched_via_spdy);
Emily Starkf2c9bbd2019-04-09 17:08:585652 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]dc7bd1c52010-11-12 00:01:135653
[email protected]49639fa2011-12-20 23:22:415654 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:135655
bnc691fda62016-08-12 00:43:165656 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015657 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:135658
5659 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015660 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:135661
bnc691fda62016-08-12 00:43:165662 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
[email protected]dc7bd1c52010-11-12 00:01:135663
wezca1070932016-05-26 20:30:525664 ASSERT_TRUE(response_restart);
5665 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:135666 EXPECT_EQ(200, response_restart->headers->response_code());
5667 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:585668 EXPECT_FALSE(response_restart->auth_challenge.has_value());
[email protected]dc7bd1c52010-11-12 00:01:135669}
5670
[email protected]d9da5fe2010-10-13 22:37:165671// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:015672TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:275673 HttpRequestInfo request;
5674 request.method = "GET";
bncce36dca22015-04-21 22:11:235675 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105676 request.traffic_annotation =
5677 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275678
[email protected]d9da5fe2010-10-13 22:37:165679 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495680 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5681 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515682 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075683 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095684 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165685
bnc691fda62016-08-12 00:43:165686 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165687
bncce36dca22015-04-21 22:11:235688 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135689 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045690 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5691 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235692 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:165693
bncce36dca22015-04-21 22:11:235694 const char get[] =
5695 "GET / HTTP/1.1\r\n"
5696 "Host: www.example.org\r\n"
5697 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135698 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:195699 spdy_util_.ConstructSpdyDataFrame(1, get, false));
Ryan Hamilton0239aac2018-05-19 00:03:135700 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355701 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:165702 const char resp[] = "HTTP/1.1 200 OK\r\n"
5703 "Content-Length: 10\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:135704 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:195705 spdy_util_.ConstructSpdyDataFrame(1, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:135706 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:195707 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", false));
Ryan Hamilton0239aac2018-05-19 00:03:135708 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:415709 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:045710
5711 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415712 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5713 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:045714 };
5715
[email protected]d9da5fe2010-10-13 22:37:165716 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415717 CreateMockRead(conn_resp, 1, ASYNC),
5718 CreateMockRead(wrapped_get_resp, 3, ASYNC),
5719 CreateMockRead(wrapped_body, 4, ASYNC),
5720 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135721 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:165722 };
5723
Ryan Sleevib8d7ea02018-05-07 20:01:015724 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075725 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165726
[email protected]8ddf8322012-02-23 18:08:065727 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365728 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075729 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065730 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075731 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165732
[email protected]49639fa2011-12-20 23:22:415733 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165734
bnc691fda62016-08-12 00:43:165735 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015736 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165737
5738 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015739 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165740
[email protected]58e32bb2013-01-21 18:23:255741 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165742 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255743 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5744
bnc691fda62016-08-12 00:43:165745 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525746 ASSERT_TRUE(response);
5747 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:165748 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5749
5750 std::string response_data;
bnc691fda62016-08-12 00:43:165751 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:165752 EXPECT_EQ("1234567890", response_data);
5753}
5754
5755// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:015756TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
5757 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:385758
[email protected]cb9bf6ca2011-01-28 13:15:275759 HttpRequestInfo request;
5760 request.method = "GET";
bncce36dca22015-04-21 22:11:235761 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105762 request.traffic_annotation =
5763 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275764
[email protected]d9da5fe2010-10-13 22:37:165765 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495766 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5767 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515768 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075769 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095770 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165771
bnc691fda62016-08-12 00:43:165772 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165773
bncce36dca22015-04-21 22:11:235774 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135775 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045776 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5777 HostPortPair("www.example.org", 443)));
bncce36dca22015-04-21 22:11:235778 // fetch https://www.example.org/ via SPDY
5779 const char kMyUrl[] = "https://www.example.org/";
Ryan Hamilton0239aac2018-05-19 00:03:135780 spdy::SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:495781 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:135782 spdy::SpdySerializedFrame wrapped_get(
5783 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
5784 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:355785 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135786 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355787 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135788 spdy::SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:025789 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135790 spdy::SpdySerializedFrame body(
5791 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
5792 spdy::SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:025793 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
Ryan Hamilton0239aac2018-05-19 00:03:135794 spdy::SpdySerializedFrame window_update_get_resp(
bncdf80d44fd2016-07-15 20:27:415795 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
Ryan Hamilton0239aac2018-05-19 00:03:135796 spdy::SpdySerializedFrame window_update_body(
bncdf80d44fd2016-07-15 20:27:415797 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:045798
5799 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415800 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
5801 CreateMockWrite(window_update_get_resp, 6),
5802 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:045803 };
5804
[email protected]d9da5fe2010-10-13 22:37:165805 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415806 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:095807 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:415808 CreateMockRead(wrapped_get_resp, 4, ASYNC),
5809 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:135810 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:165811 };
5812
Ryan Sleevib8d7ea02018-05-07 20:01:015813 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075814 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165815
[email protected]8ddf8322012-02-23 18:08:065816 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365817 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075818 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065819 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365820 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075821 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165822
[email protected]49639fa2011-12-20 23:22:415823 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165824
bnc691fda62016-08-12 00:43:165825 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015826 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165827
rch32320842015-05-16 15:57:095828 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:555829 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:095830 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:595831 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:165832 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015833 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:165834
[email protected]58e32bb2013-01-21 18:23:255835 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:165836 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:255837 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5838
bnc691fda62016-08-12 00:43:165839 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:525840 ASSERT_TRUE(response);
5841 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025842 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:165843
5844 std::string response_data;
bnc691fda62016-08-12 00:43:165845 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:235846 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:165847}
5848
5849// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:015850TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:275851 HttpRequestInfo request;
5852 request.method = "GET";
bncce36dca22015-04-21 22:11:235853 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:105854 request.traffic_annotation =
5855 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:275856
[email protected]d9da5fe2010-10-13 22:37:165857 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:495858 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
5859 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:515860 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075861 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:165863
bnc691fda62016-08-12 00:43:165864 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]d9da5fe2010-10-13 22:37:165865
bncce36dca22015-04-21 22:11:235866 // CONNECT to www.example.org:443 via SPDY
Ryan Hamilton0239aac2018-05-19 00:03:135867 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:045868 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
5869 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:135870 spdy::SpdySerializedFrame get(
5871 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:165872
5873 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415874 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:165875 };
5876
Ryan Hamilton0239aac2018-05-19 00:03:135877 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
5878 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:165879 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415880 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:165881 };
5882
Ryan Sleevib8d7ea02018-05-07 20:01:015883 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:075884 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:165885
[email protected]8ddf8322012-02-23 18:08:065886 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365887 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075888 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:065889 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365890 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:075891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:165892
[email protected]49639fa2011-12-20 23:22:415893 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:165894
bnc691fda62016-08-12 00:43:165895 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015896 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:165897
5898 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015899 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:165900
ttuttle960fcbf2016-04-19 13:26:325901 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:165902}
5903
Matt Menkecb2cd0982018-12-19 17:54:045904// Test the case where a proxied H2 session doesn't exist when an auth challenge
Matt Menke5062be22019-05-01 17:50:245905// is observed, but does exist by the time auth credentials are provided. In
5906// this case, auth and SSL are fully negotated on the second request, but then
5907// the socket is discarded to use the shared session.
Matt Menkecb2cd0982018-12-19 17:54:045908TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
5909 ProxyConfig proxy_config;
5910 proxy_config.set_auto_detect(true);
5911 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
5912
5913 CapturingProxyResolver capturing_proxy_resolver;
5914 capturing_proxy_resolver.set_proxy_server(
5915 ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
5916 session_deps_.proxy_resolution_service =
5917 std::make_unique<ProxyResolutionService>(
5918 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
5919 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
5920 std::make_unique<CapturingProxyResolverFactory>(
5921 &capturing_proxy_resolver),
5922 nullptr);
5923
5924 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5925
5926 const char kMyUrl[] = "https://www.example.org/";
5927 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
5928 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:355929 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menkecb2cd0982018-12-19 17:54:045930 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
5931
5932 spdy_util_.UpdateWithStreamDestruction(1);
5933 spdy::SpdySerializedFrame get2(
5934 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
5935 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:355936 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Matt Menkecb2cd0982018-12-19 17:54:045937 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
5938
5939 MockWrite auth_challenge_writes[] = {
5940 MockWrite(ASYNC, 0,
5941 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5942 "Host: www.example.org:443\r\n"
5943 "Proxy-Connection: keep-alive\r\n\r\n"),
Matt Menke5062be22019-05-01 17:50:245944 MockWrite(ASYNC, 2,
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"),
Matt Menkecb2cd0982018-12-19 17:54:045948 };
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
Matt Menke5062be22019-05-01 17:50:245978 MockWrite auth_response_writes_discarded_socket[] = {
5979 MockWrite(ASYNC, 0,
5980 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5981 "Host: www.example.org:443\r\n"
5982 "Proxy-Connection: keep-alive\r\n"
5983 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5984 };
5985
5986 MockRead auth_response_reads_discarded_socket[] = {
5987 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
5988 };
5989
Matt Menkecb2cd0982018-12-19 17:54:045990 SequencedSocketData auth_challenge1(auth_challenge_reads,
5991 auth_challenge_writes);
5992 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
5993
5994 SequencedSocketData auth_challenge2(auth_challenge_reads,
5995 auth_challenge_writes);
5996 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
5997
5998 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
5999 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6000
Matt Menke5062be22019-05-01 17:50:246001 SequencedSocketData auth_response_discarded_socket(
6002 auth_response_reads_discarded_socket,
6003 auth_response_writes_discarded_socket);
6004 session_deps_.socket_factory->AddSocketDataProvider(
6005 &auth_response_discarded_socket);
6006
Matt Menkecb2cd0982018-12-19 17:54:046007 SSLSocketDataProvider ssl(ASYNC, OK);
6008 ssl.next_proto = kProtoHTTP2;
6009 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6010
Matt Menke5062be22019-05-01 17:50:246011 SSLSocketDataProvider ssl2(ASYNC, OK);
6012 ssl2.next_proto = kProtoHTTP2;
6013 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6014
Matt Menkecb2cd0982018-12-19 17:54:046015 TestCompletionCallback callback;
6016 std::string response_data;
6017
6018 // Run first request until an auth challenge is observed.
6019 HttpRequestInfo request1;
6020 request1.method = "GET";
6021 request1.url = GURL(kMyUrl);
6022 request1.traffic_annotation =
6023 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6024 HttpNetworkTransaction trans1(LOWEST, session.get());
6025 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6026 EXPECT_THAT(callback.GetResult(rv), IsOk());
6027 const HttpResponseInfo* response = trans1.GetResponseInfo();
6028 ASSERT_TRUE(response);
6029 ASSERT_TRUE(response->headers);
6030 EXPECT_EQ(407, response->headers->response_code());
6031 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586032 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046033
6034 // Run second request until an auth challenge is observed.
6035 HttpRequestInfo request2;
6036 request2.method = "GET";
6037 request2.url = GURL(kMyUrl);
6038 request2.traffic_annotation =
6039 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6040 HttpNetworkTransaction trans2(LOWEST, session.get());
6041 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6042 EXPECT_THAT(callback.GetResult(rv), IsOk());
6043 response = trans2.GetResponseInfo();
6044 ASSERT_TRUE(response);
6045 ASSERT_TRUE(response->headers);
6046 EXPECT_EQ(407, response->headers->response_code());
6047 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586048 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
Matt Menkecb2cd0982018-12-19 17:54:046049
6050 // Now provide credentials for the first request, and wait for it to complete.
6051 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6052 rv = callback.GetResult(rv);
6053 EXPECT_THAT(rv, IsOk());
6054 response = trans1.GetResponseInfo();
6055 ASSERT_TRUE(response);
6056 ASSERT_TRUE(response->headers);
6057 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6058 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6059 EXPECT_EQ(kUploadData, response_data);
6060
6061 // Now provide credentials for the second request. It should notice the
6062 // existing session, and reuse it.
6063 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
6064 EXPECT_THAT(callback.GetResult(rv), IsOk());
6065 response = trans2.GetResponseInfo();
6066 ASSERT_TRUE(response);
6067 ASSERT_TRUE(response->headers);
6068 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6069 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6070 EXPECT_EQ(kUploadData, response_data);
6071}
6072
[email protected]f6c63db52013-02-02 00:35:226073// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6074// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:016075TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226076 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
6077 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496078 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6079 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516080 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076081 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096082 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506083 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226084
6085 HttpRequestInfo request1;
6086 request1.method = "GET";
bncce36dca22015-04-21 22:11:236087 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226088 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106089 request1.traffic_annotation =
6090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226091
6092 HttpRequestInfo request2;
6093 request2.method = "GET";
bncce36dca22015-04-21 22:11:236094 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226095 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106096 request2.traffic_annotation =
6097 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226098
bncce36dca22015-04-21 22:11:236099 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136100 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046101 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6102 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136103 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356104 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226105
bncce36dca22015-04-21 22:11:236106 // Fetch https://www.example.org/ via HTTP.
6107 const char get1[] =
6108 "GET / HTTP/1.1\r\n"
6109 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226110 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136111 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196112 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226113 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6114 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136115 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196116 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136117 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196118 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136119 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416120 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226121
bncce36dca22015-04-21 22:11:236122 // CONNECT to mail.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136123 spdy::SpdyHeaderBlock connect2_block;
6124 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
6125 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
6126 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
Matt Menke6e879bd2019-03-18 17:26:046127 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
6128 false));
[email protected]601e03f12014-04-06 16:26:396129
Ryan Hamilton0239aac2018-05-19 00:03:136130 spdy::SpdySerializedFrame conn_resp2(
Raul Tambre94493c652019-03-11 17:18:356131 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]f6c63db52013-02-02 00:35:226132
bncce36dca22015-04-21 22:11:236133 // Fetch https://mail.example.org/ via HTTP.
6134 const char get2[] =
6135 "GET / HTTP/1.1\r\n"
6136 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226137 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136138 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196139 spdy_util_.ConstructSpdyDataFrame(3, get2, false));
[email protected]f6c63db52013-02-02 00:35:226140 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6141 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136142 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196143 spdy_util_.ConstructSpdyDataFrame(3, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136144 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196145 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
[email protected]f6c63db52013-02-02 00:35:226146
6147 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416148 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6149 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:226150 };
6151
6152 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416153 CreateMockRead(conn_resp1, 1, ASYNC),
6154 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
6155 CreateMockRead(wrapped_body1, 4, ASYNC),
6156 CreateMockRead(conn_resp2, 6, ASYNC),
6157 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
6158 CreateMockRead(wrapped_body2, 9, ASYNC),
6159 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:226160 };
6161
Ryan Sleevib8d7ea02018-05-07 20:01:016162 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506163 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226164
6165 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366166 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226168 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506169 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226170 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:226172
6173 TestCompletionCallback callback;
6174
bnc691fda62016-08-12 00:43:166175 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206176 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016177 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226178
6179 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166180 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]f6c63db52013-02-02 00:35:226181 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6182
bnc691fda62016-08-12 00:43:166183 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526184 ASSERT_TRUE(response);
6185 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226186 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6187
6188 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446189 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
bnc691fda62016-08-12 00:43:166190 rv = trans.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506191 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226192
bnc691fda62016-08-12 00:43:166193 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206194 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016195 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226196
6197 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166198 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226199 // Even though the SPDY connection is reused, a new tunnelled connection has
6200 // to be created, so the socket's load timing looks like a fresh connection.
6201 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
6202
6203 // The requests should have different IDs, since they each are using their own
6204 // separate stream.
6205 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6206
bnc691fda62016-08-12 00:43:166207 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506208 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226209}
6210
6211// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
6212// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:016213TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:226214 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
6215 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496216 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6217 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516218 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076219 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096220 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506221 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226222
6223 HttpRequestInfo request1;
6224 request1.method = "GET";
bncce36dca22015-04-21 22:11:236225 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226226 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106227 request1.traffic_annotation =
6228 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226229
6230 HttpRequestInfo request2;
6231 request2.method = "GET";
bncce36dca22015-04-21 22:11:236232 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:226233 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106234 request2.traffic_annotation =
6235 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226236
bncce36dca22015-04-21 22:11:236237 // CONNECT to www.example.org:443 via SPDY.
Ryan Hamilton0239aac2018-05-19 00:03:136238 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046239 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6240 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:136241 spdy::SpdySerializedFrame conn_resp1(
Raul Tambre94493c652019-03-11 17:18:356242 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]f6c63db52013-02-02 00:35:226243
bncce36dca22015-04-21 22:11:236244 // Fetch https://www.example.org/ via HTTP.
6245 const char get1[] =
6246 "GET / HTTP/1.1\r\n"
6247 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226248 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136249 spdy::SpdySerializedFrame wrapped_get1(
Bence Békyd74f4382018-02-20 18:26:196250 spdy_util_.ConstructSpdyDataFrame(1, get1, false));
[email protected]f6c63db52013-02-02 00:35:226251 const char resp1[] = "HTTP/1.1 200 OK\r\n"
6252 "Content-Length: 1\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136253 spdy::SpdySerializedFrame wrapped_get_resp1(
Bence Békyd74f4382018-02-20 18:26:196254 spdy_util_.ConstructSpdyDataFrame(1, resp1, false));
Ryan Hamilton0239aac2018-05-19 00:03:136255 spdy::SpdySerializedFrame wrapped_body1(
Bence Békyd74f4382018-02-20 18:26:196256 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
Ryan Hamilton0239aac2018-05-19 00:03:136257 spdy::SpdySerializedFrame window_update(
bncdf80d44fd2016-07-15 20:27:416258 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:226259
bncce36dca22015-04-21 22:11:236260 // Fetch https://www.example.org/2 via HTTP.
6261 const char get2[] =
6262 "GET /2 HTTP/1.1\r\n"
6263 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:226264 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136265 spdy::SpdySerializedFrame wrapped_get2(
Bence Békyd74f4382018-02-20 18:26:196266 spdy_util_.ConstructSpdyDataFrame(1, get2, false));
[email protected]f6c63db52013-02-02 00:35:226267 const char resp2[] = "HTTP/1.1 200 OK\r\n"
6268 "Content-Length: 2\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:136269 spdy::SpdySerializedFrame wrapped_get_resp2(
Bence Békyd74f4382018-02-20 18:26:196270 spdy_util_.ConstructSpdyDataFrame(1, resp2, false));
Ryan Hamilton0239aac2018-05-19 00:03:136271 spdy::SpdySerializedFrame wrapped_body2(
Bence Békyd74f4382018-02-20 18:26:196272 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
[email protected]f6c63db52013-02-02 00:35:226273
6274 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416275 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
6276 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:226277 };
6278
6279 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416280 CreateMockRead(conn_resp1, 1, ASYNC),
6281 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
bnceb9aa7112017-01-05 01:03:466282 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416283 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
bnceb9aa7112017-01-05 01:03:466284 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
bncdf80d44fd2016-07-15 20:27:416285 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:226286 };
6287
Ryan Sleevib8d7ea02018-05-07 20:01:016288 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506289 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226290
6291 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366292 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506293 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226294 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:506295 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:226296
6297 TestCompletionCallback callback;
6298
bnc87dcefc2017-05-25 12:47:586299 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196300 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206301 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016302 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226303
6304 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_info;
6308 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6309 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
6310
6311 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526312 ASSERT_TRUE(response);
6313 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:226314 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6315
6316 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446317 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
[email protected]90499482013-06-01 00:39:506318 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226319 trans.reset();
6320
bnc87dcefc2017-05-25 12:47:586321 auto trans2 =
Jeremy Roman0579ed62017-08-29 15:56:196322 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206323 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016324 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:226325
[email protected]f6c63db52013-02-02 00:35:226326 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016327 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:226328
6329 LoadTimingInfo load_timing_info2;
6330 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6331 TestLoadTimingReused(load_timing_info2);
6332
6333 // The requests should have the same ID.
6334 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6335
[email protected]90499482013-06-01 00:39:506336 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:226337}
6338
6339// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
6340// Proxy to different servers.
bncd16676a2016-07-20 16:23:016341TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:226342 // Configure against https proxy server "proxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496343 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6344 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516345 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076346 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096347 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:506348 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:226349
6350 HttpRequestInfo request1;
6351 request1.method = "GET";
bncce36dca22015-04-21 22:11:236352 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:226353 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106354 request1.traffic_annotation =
6355 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226356
6357 HttpRequestInfo request2;
6358 request2.method = "GET";
bncce36dca22015-04-21 22:11:236359 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:226360 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:106361 request2.traffic_annotation =
6362 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f6c63db52013-02-02 00:35:226363
bncce36dca22015-04-21 22:11:236364 // http://www.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136365 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:236366 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136367 spdy::SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:156368 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136369 spdy::SpdySerializedFrame get_resp1(
Raul Tambre94493c652019-03-11 17:18:356370 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:136371 spdy::SpdySerializedFrame body1(
6372 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
rdsmithebb50aa2015-11-12 03:44:386373 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:226374
bncce36dca22015-04-21 22:11:236375 // http://mail.example.org/
Ryan Hamilton0239aac2018-05-19 00:03:136376 spdy::SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:236377 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:136378 spdy::SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:156379 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
Ryan Hamilton0239aac2018-05-19 00:03:136380 spdy::SpdySerializedFrame get_resp2(
Raul Tambre94493c652019-03-11 17:18:356381 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:136382 spdy::SpdySerializedFrame body2(
6383 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
[email protected]f6c63db52013-02-02 00:35:226384
6385 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:416386 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:226387 };
6388
6389 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:416390 CreateMockRead(get_resp1, 1, ASYNC),
6391 CreateMockRead(body1, 2, ASYNC),
6392 CreateMockRead(get_resp2, 4, ASYNC),
6393 CreateMockRead(body2, 5, ASYNC),
6394 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:226395 };
6396
Ryan Sleevib8d7ea02018-05-07 20:01:016397 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
mmenke11eb5152015-06-09 14:50:506398 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:226399
6400 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:366401 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:506402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:226403
6404 TestCompletionCallback callback;
6405
bnc87dcefc2017-05-25 12:47:586406 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:196407 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206408 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016409 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226410
6411 LoadTimingInfo load_timing_info;
6412 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6413 TestLoadTimingNotReused(load_timing_info,
6414 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6415
6416 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526417 ASSERT_TRUE(response);
6418 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:026419 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:226420
6421 std::string response_data;
Victor Costan9c7302b2018-08-27 16:39:446422 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
mmenke11eb5152015-06-09 14:50:506423 rv = trans->Read(buf.get(), 256, callback.callback());
6424 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226425 // Delete the first request, so the second one can reuse the socket.
6426 trans.reset();
6427
bnc691fda62016-08-12 00:43:166428 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:206429 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016430 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:226431
6432 LoadTimingInfo load_timing_info2;
bnc691fda62016-08-12 00:43:166433 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
[email protected]f6c63db52013-02-02 00:35:226434 TestLoadTimingReused(load_timing_info2);
6435
6436 // The requests should have the same ID.
6437 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
6438
bnc691fda62016-08-12 00:43:166439 rv = trans2.Read(buf.get(), 256, callback.callback());
mmenke11eb5152015-06-09 14:50:506440 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:226441}
6442
Matt Menke2436b2f2018-12-11 18:07:116443// Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
6444// direct (non-proxied) request to the proxy server are not pooled, as that
6445// would break socket pool isolation.
6446TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
6447 ProxyConfig proxy_config;
6448 proxy_config.set_auto_detect(true);
6449 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6450
6451 CapturingProxyResolver capturing_proxy_resolver;
6452 session_deps_.proxy_resolution_service =
6453 std::make_unique<ProxyResolutionService>(
6454 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6455 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6456 std::make_unique<CapturingProxyResolverFactory>(
6457 &capturing_proxy_resolver),
6458 nullptr);
6459
6460 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6461
6462 SpdyTestUtil spdy_util1;
6463 // CONNECT to www.example.org:443 via HTTP/2.
6464 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046465 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6466 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116467 // fetch https://www.example.org/ via HTTP/2.
6468 const char kMyUrl[] = "https://www.example.org/";
6469 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6470 spdy::SpdySerializedFrame wrapped_get(
6471 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6472 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:356473 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116474 spdy::SpdySerializedFrame get_resp(
Raul Tambre94493c652019-03-11 17:18:356475 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
Matt Menke2436b2f2018-12-11 18:07:116476 spdy::SpdySerializedFrame wrapped_get_resp(
6477 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6478 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
6479 spdy::SpdySerializedFrame wrapped_body(
6480 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6481 spdy::SpdySerializedFrame window_update_get_resp(
6482 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6483 spdy::SpdySerializedFrame window_update_body(
6484 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6485
6486 MockWrite spdy_writes1[] = {
6487 CreateMockWrite(connect, 0),
6488 CreateMockWrite(wrapped_get, 2),
6489 CreateMockWrite(window_update_get_resp, 6),
6490 CreateMockWrite(window_update_body, 7),
6491 };
6492
6493 MockRead spdy_reads1[] = {
6494 CreateMockRead(conn_resp, 1, ASYNC),
6495 MockRead(ASYNC, ERR_IO_PENDING, 3),
6496 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6497 CreateMockRead(wrapped_body, 5, ASYNC),
6498 MockRead(ASYNC, 0, 8),
6499 };
6500
6501 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6502 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6503
6504 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
6505 // a new pipe.
6506 SpdyTestUtil spdy_util2;
6507 spdy::SpdySerializedFrame req(
6508 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6509 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
6510
6511 spdy::SpdySerializedFrame resp(
6512 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6513 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
6514 MockRead spdy_reads2[] = {
6515 CreateMockRead(resp, 1),
6516 CreateMockRead(data, 2),
6517 MockRead(ASYNC, 0, 3),
6518 };
6519 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6520 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6521
6522 SSLSocketDataProvider ssl(ASYNC, OK);
6523 ssl.next_proto = kProtoHTTP2;
6524 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6525 SSLSocketDataProvider ssl2(ASYNC, OK);
6526 ssl2.next_proto = kProtoHTTP2;
6527 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6528 SSLSocketDataProvider ssl3(ASYNC, OK);
6529 ssl3.next_proto = kProtoHTTP2;
6530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6531
6532 TestCompletionCallback callback;
6533 std::string response_data;
6534
6535 // Make a request using proxy:70 as a HTTP/2 proxy.
6536 capturing_proxy_resolver.set_proxy_server(
6537 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6538 HttpRequestInfo request1;
6539 request1.method = "GET";
6540 request1.url = GURL("https://www.example.org/");
6541 request1.traffic_annotation =
6542 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6543
6544 HttpNetworkTransaction trans1(LOWEST, session.get());
6545 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
6546 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6547
6548 // Allow the SpdyProxyClientSocket's write callback to complete.
6549 base::RunLoop().RunUntilIdle();
6550 // Now allow the read of the response to complete.
6551 spdy_data1.Resume();
6552 rv = callback.WaitForResult();
6553 EXPECT_THAT(rv, IsOk());
6554
6555 const HttpResponseInfo* response = trans1.GetResponseInfo();
6556 ASSERT_TRUE(response);
6557 ASSERT_TRUE(response->headers);
6558 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6559
6560 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6561 EXPECT_EQ(kUploadData, response_data);
6562 RunUntilIdle();
6563
6564 // Make a direct HTTP/2 request to proxy:70.
6565 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6566 HttpRequestInfo request2;
6567 request2.method = "GET";
6568 request2.url = GURL("https://proxy:70/");
6569 request2.traffic_annotation =
6570 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6571 HttpNetworkTransaction trans2(LOWEST, session.get());
6572 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
6573 NetLogWithSource())),
6574 IsOk());
6575 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6576}
6577
6578// Same as above, but reverse request order, since the code to check for an
6579// existing session is different for tunnels and direct connections.
6580TEST_F(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
6581 // Configure against https proxy server "myproxy:80".
6582 ProxyConfig proxy_config;
6583 proxy_config.set_auto_detect(true);
6584 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6585
6586 CapturingProxyResolver capturing_proxy_resolver;
6587 session_deps_.proxy_resolution_service =
6588 std::make_unique<ProxyResolutionService>(
6589 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6590 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6591 std::make_unique<CapturingProxyResolverFactory>(
6592 &capturing_proxy_resolver),
6593 nullptr);
6594
6595 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6596 // Fetch https://proxy:70/ via HTTP/2.
6597 SpdyTestUtil spdy_util1;
6598 spdy::SpdySerializedFrame req(
6599 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
6600 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
6601
6602 spdy::SpdySerializedFrame resp(
6603 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
6604 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
6605 MockRead spdy_reads1[] = {
6606 CreateMockRead(resp, 1),
6607 CreateMockRead(data, 2),
6608 MockRead(ASYNC, 0, 3),
6609 };
6610 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
6611 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
6612
6613 SpdyTestUtil spdy_util2;
6614 // CONNECT to www.example.org:443 via HTTP/2.
6615 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:046616 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
6617 HostPortPair("www.example.org", 443)));
Matt Menke2436b2f2018-12-11 18:07:116618 // fetch https://www.example.org/ via HTTP/2.
6619 const char kMyUrl[] = "https://www.example.org/";
6620 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
6621 spdy::SpdySerializedFrame wrapped_get(
6622 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
6623 spdy::SpdySerializedFrame conn_resp(
6624 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6625 spdy::SpdySerializedFrame get_resp(
6626 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6627 spdy::SpdySerializedFrame wrapped_get_resp(
6628 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
6629 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
6630 spdy::SpdySerializedFrame wrapped_body(
6631 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
6632 spdy::SpdySerializedFrame window_update_get_resp(
6633 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
6634 spdy::SpdySerializedFrame window_update_body(
6635 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
6636
6637 MockWrite spdy_writes2[] = {
6638 CreateMockWrite(connect, 0),
6639 CreateMockWrite(wrapped_get, 2),
6640 CreateMockWrite(window_update_get_resp, 6),
6641 CreateMockWrite(window_update_body, 7),
6642 };
6643
6644 MockRead spdy_reads2[] = {
6645 CreateMockRead(conn_resp, 1, ASYNC),
6646 MockRead(ASYNC, ERR_IO_PENDING, 3),
6647 CreateMockRead(wrapped_get_resp, 4, ASYNC),
6648 CreateMockRead(wrapped_body, 5, ASYNC),
6649 MockRead(ASYNC, 0, 8),
6650 };
6651
6652 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
6653 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
6654
6655 SSLSocketDataProvider ssl(ASYNC, OK);
6656 ssl.next_proto = kProtoHTTP2;
6657 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6658 SSLSocketDataProvider ssl2(ASYNC, OK);
6659 ssl2.next_proto = kProtoHTTP2;
6660 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6661 SSLSocketDataProvider ssl3(ASYNC, OK);
6662 ssl3.next_proto = kProtoHTTP2;
6663 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
6664
6665 TestCompletionCallback callback;
6666 std::string response_data;
6667
6668 // Make a direct HTTP/2 request to proxy:70.
6669 capturing_proxy_resolver.set_proxy_server(ProxyServer::Direct());
6670 HttpRequestInfo request1;
6671 request1.method = "GET";
6672 request1.url = GURL("https://proxy:70/");
6673 request1.traffic_annotation =
6674 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6675 HttpNetworkTransaction trans1(LOWEST, session.get());
6676 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
6677 NetLogWithSource())),
6678 IsOk());
6679 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
6680 RunUntilIdle();
6681
6682 // Make a request using proxy:70 as a HTTP/2 proxy.
6683 capturing_proxy_resolver.set_proxy_server(
6684 ProxyServer(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
6685 HttpRequestInfo request2;
6686 request2.method = "GET";
6687 request2.url = GURL("https://www.example.org/");
6688 request2.traffic_annotation =
6689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6690
6691 HttpNetworkTransaction trans2(LOWEST, session.get());
6692 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
6693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6694
6695 // Allow the SpdyProxyClientSocket's write callback to complete.
6696 base::RunLoop().RunUntilIdle();
6697 // Now allow the read of the response to complete.
6698 spdy_data2.Resume();
6699 rv = callback.WaitForResult();
6700 EXPECT_THAT(rv, IsOk());
6701
6702 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
6703 ASSERT_TRUE(response2);
6704 ASSERT_TRUE(response2->headers);
6705 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
6706
6707 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
6708 EXPECT_EQ(kUploadData, response_data);
6709}
6710
[email protected]2df19bb2010-08-25 20:13:466711// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:016712TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:466713 HttpRequestInfo request;
6714 request.method = "GET";
bncce36dca22015-04-21 22:11:236715 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:466716 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:296717 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:106718 request.traffic_annotation =
6719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:466720
[email protected]79cb5c12011-09-12 13:12:046721 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496722 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6723 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:516724 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:076725 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:096726 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276727
[email protected]2df19bb2010-08-25 20:13:466728 // Since we have proxy, should use full url
6729 MockWrite data_writes1[] = {
bnc691fda62016-08-12 00:43:166730 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6731 "Host: www.example.org\r\n"
6732 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466733
bnc691fda62016-08-12 00:43:166734 // After calling trans.RestartWithAuth(), this is the request we should
bncce36dca22015-04-21 22:11:236735 // be issuing -- the final header line contains the credentials.
bnc691fda62016-08-12 00:43:166736 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6737 "Host: www.example.org\r\n"
6738 "Proxy-Connection: keep-alive\r\n"
6739 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:466740 };
6741
6742 // The proxy responds to the GET with a 407, using a persistent
6743 // connection.
6744 MockRead data_reads1[] = {
6745 // No credentials.
6746 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6747 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6748 MockRead("Proxy-Connection: keep-alive\r\n"),
6749 MockRead("Content-Length: 0\r\n\r\n"),
6750
6751 MockRead("HTTP/1.1 200 OK\r\n"),
6752 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6753 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066754 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:466755 };
6756
Ryan Sleevib8d7ea02018-05-07 20:01:016757 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:076758 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:066759 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:466761
[email protected]49639fa2011-12-20 23:22:416762 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:466763
bnc691fda62016-08-12 00:43:166764 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506765
bnc691fda62016-08-12 00:43:166766 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:016767 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466768
6769 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016770 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466771
[email protected]58e32bb2013-01-21 18:23:256772 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:166773 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256774 TestLoadTimingNotReused(load_timing_info,
6775 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6776
bnc691fda62016-08-12 00:43:166777 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526778 ASSERT_TRUE(response);
6779 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:466780 EXPECT_EQ(407, response->headers->response_code());
6781 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:586782 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
Wojciech Dzierżanowski0950c372019-04-02 19:29:506783 EXPECT_FALSE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466784
[email protected]49639fa2011-12-20 23:22:416785 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:466786
bnc691fda62016-08-12 00:43:166787 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016788 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:466789
6790 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016791 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:466792
[email protected]58e32bb2013-01-21 18:23:256793 load_timing_info = LoadTimingInfo();
bnc691fda62016-08-12 00:43:166794 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]58e32bb2013-01-21 18:23:256795 // Retrying with HTTP AUTH is considered to be reusing a socket.
6796 TestLoadTimingReused(load_timing_info);
6797
bnc691fda62016-08-12 00:43:166798 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:526799 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:466800
6801 EXPECT_TRUE(response->headers->IsKeepAlive());
6802 EXPECT_EQ(200, response->headers->response_code());
6803 EXPECT_EQ(100, response->headers->GetContentLength());
6804 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Wojciech Dzierżanowski0950c372019-04-02 19:29:506805 EXPECT_TRUE(response->did_use_http_auth);
[email protected]2df19bb2010-08-25 20:13:466806
6807 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:586808 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2df19bb2010-08-25 20:13:466809}
6810
[email protected]23e482282013-06-14 16:08:026811void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:086812 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:426813 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:086814 request.method = "GET";
bncce36dca22015-04-21 22:11:236815 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:106816 request.traffic_annotation =
6817 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c744cf22009-02-27 07:28:086818
[email protected]cb9bf6ca2011-01-28 13:15:276819 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:496820 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
6821 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:096822 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276823
[email protected]c744cf22009-02-27 07:28:086824 // Since we have proxy, should try to establish tunnel.
6825 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:176826 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6827 "Host: www.example.org:443\r\n"
6828 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:086829 };
6830
6831 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:236832 status, MockRead("Content-Length: 10\r\n\r\n"),
6833 // No response body because the test stops reading here.
6834 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:086835 };
6836
Ryan Sleevib8d7ea02018-05-07 20:01:016837 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:076838 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:086839
[email protected]49639fa2011-12-20 23:22:416840 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:086841
bnc691fda62016-08-12 00:43:166842 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:506843
tfarina42834112016-09-22 13:38:206844 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:016845 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:086846
6847 rv = callback.WaitForResult();
6848 EXPECT_EQ(expected_status, rv);
6849}
6850
[email protected]23e482282013-06-14 16:08:026851void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:236852 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:086853 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:426854 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:086855}
6856
bncd16676a2016-07-20 16:23:016857TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:086858 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
6859}
6860
bncd16676a2016-07-20 16:23:016861TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:086862 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
6863}
6864
bncd16676a2016-07-20 16:23:016865TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:086866 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
6867}
6868
bncd16676a2016-07-20 16:23:016869TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:086870 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
6871}
6872
bncd16676a2016-07-20 16:23:016873TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:086874 ConnectStatusHelper(
6875 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
6876}
6877
bncd16676a2016-07-20 16:23:016878TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:086879 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
6880}
6881
bncd16676a2016-07-20 16:23:016882TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:086883 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
6884}
6885
bncd16676a2016-07-20 16:23:016886TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:086887 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
6888}
6889
bncd16676a2016-07-20 16:23:016890TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:086891 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
6892}
6893
bncd16676a2016-07-20 16:23:016894TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:086895 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
6896}
6897
bncd16676a2016-07-20 16:23:016898TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:086899 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
6900}
6901
bncd16676a2016-07-20 16:23:016902TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:086903 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
6904}
6905
bncd16676a2016-07-20 16:23:016906TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:086907 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
6908}
6909
bncd16676a2016-07-20 16:23:016910TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:086911 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
6912}
6913
bncd16676a2016-07-20 16:23:016914TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:086915 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
6916}
6917
bncd16676a2016-07-20 16:23:016918TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:086919 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
6920}
6921
bncd16676a2016-07-20 16:23:016922TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:376923 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
6924}
6925
bncd16676a2016-07-20 16:23:016926TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:086927 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
6928}
6929
bncd16676a2016-07-20 16:23:016930TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:086931 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
6932}
6933
bncd16676a2016-07-20 16:23:016934TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:086935 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
6936}
6937
bncd16676a2016-07-20 16:23:016938TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:086939 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
6940}
6941
bncd16676a2016-07-20 16:23:016942TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:086943 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
6944}
6945
bncd16676a2016-07-20 16:23:016946TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:086947 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
6948}
6949
bncd16676a2016-07-20 16:23:016950TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:086951 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
6952}
6953
bncd16676a2016-07-20 16:23:016954TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:086955 ConnectStatusHelperWithExpectedStatus(
6956 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:546957 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:086958}
6959
bncd16676a2016-07-20 16:23:016960TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:086961 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
6962}
6963
bncd16676a2016-07-20 16:23:016964TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:086965 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
6966}
6967
bncd16676a2016-07-20 16:23:016968TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:086969 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
6970}
6971
bncd16676a2016-07-20 16:23:016972TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:086973 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
6974}
6975
bncd16676a2016-07-20 16:23:016976TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:086977 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
6978}
6979
bncd16676a2016-07-20 16:23:016980TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:086981 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
6982}
6983
bncd16676a2016-07-20 16:23:016984TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:086985 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
6986}
6987
bncd16676a2016-07-20 16:23:016988TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:086989 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
6990}
6991
bncd16676a2016-07-20 16:23:016992TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:086993 ConnectStatusHelper(
6994 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
6995}
6996
bncd16676a2016-07-20 16:23:016997TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:086998 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
6999}
7000
bncd16676a2016-07-20 16:23:017001TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:087002 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
7003}
7004
bncd16676a2016-07-20 16:23:017005TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:087006 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
7007}
7008
bncd16676a2016-07-20 16:23:017009TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:087010 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
7011}
7012
bncd16676a2016-07-20 16:23:017013TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:087014 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
7015}
7016
bncd16676a2016-07-20 16:23:017017TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:087018 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
7019}
7020
bncd16676a2016-07-20 16:23:017021TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:087022 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
7023}
7024
[email protected]038e9a32008-10-08 22:40:167025// Test the flow when both the proxy server AND origin server require
7026// authentication. Again, this uses basic auth for both since that is
7027// the simplest to mock.
bncd16676a2016-07-20 16:23:017028TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:277029 HttpRequestInfo request;
7030 request.method = "GET";
bncce36dca22015-04-21 22:11:237031 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107032 request.traffic_annotation =
7033 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277034
[email protected]038e9a32008-10-08 22:40:167035 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497036 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7037 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:097038 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:077039
bnc691fda62016-08-12 00:43:167040 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]038e9a32008-10-08 22:40:167041
[email protected]f9ee6b52008-11-08 06:46:237042 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237043 MockWrite(
7044 "GET http://www.example.org/ HTTP/1.1\r\n"
7045 "Host: www.example.org\r\n"
7046 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237047 };
7048
[email protected]038e9a32008-10-08 22:40:167049 MockRead data_reads1[] = {
7050 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
7051 // Give a couple authenticate options (only the middle one is actually
7052 // supported).
[email protected]22927ad2009-09-21 19:56:197053 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:167054 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7055 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
7056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7057 // Large content-length -- won't matter, as connection will be reset.
7058 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067059 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:167060 };
7061
bnc691fda62016-08-12 00:43:167062 // After calling trans.RestartWithAuth() the first time, this is the
[email protected]038e9a32008-10-08 22:40:167063 // request we should be issuing -- the final header line contains the
7064 // proxy's credentials.
7065 MockWrite data_writes2[] = {
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\r\n"),
[email protected]038e9a32008-10-08 22:40:167071 };
7072
7073 // Now the proxy server lets the request pass through to origin server.
7074 // The origin server responds with a 401.
7075 MockRead data_reads2[] = {
7076 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7077 // Note: We are using the same realm-name as the proxy server. This is
7078 // completely valid, as realms are unique across hosts.
7079 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7080 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7081 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067082 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:167083 };
7084
bnc691fda62016-08-12 00:43:167085 // After calling trans.RestartWithAuth() the second time, we should send
[email protected]038e9a32008-10-08 22:40:167086 // the credentials for both the proxy and origin server.
7087 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237088 MockWrite(
7089 "GET http://www.example.org/ HTTP/1.1\r\n"
7090 "Host: www.example.org\r\n"
7091 "Proxy-Connection: keep-alive\r\n"
7092 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
7093 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:167094 };
7095
7096 // Lastly we get the desired content.
7097 MockRead data_reads3[] = {
7098 MockRead("HTTP/1.0 200 OK\r\n"),
7099 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7100 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067101 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:167102 };
7103
Ryan Sleevib8d7ea02018-05-07 20:01:017104 StaticSocketDataProvider data1(data_reads1, data_writes1);
7105 StaticSocketDataProvider data2(data_reads2, data_writes2);
7106 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077107 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7108 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7109 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:167110
[email protected]49639fa2011-12-20 23:22:417111 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:167112
tfarina42834112016-09-22 13:38:207113 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017114 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167115
7116 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017117 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167118
bnc691fda62016-08-12 00:43:167119 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527120 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587121 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167122
[email protected]49639fa2011-12-20 23:22:417123 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:167124
bnc691fda62016-08-12 00:43:167125 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017126 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167127
7128 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017129 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167130
bnc691fda62016-08-12 00:43:167131 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527132 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587133 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]038e9a32008-10-08 22:40:167134
[email protected]49639fa2011-12-20 23:22:417135 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:167136
bnc691fda62016-08-12 00:43:167137 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
7138 callback3.callback());
robpercival214763f2016-07-01 23:27:017139 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:167140
7141 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017142 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:167143
bnc691fda62016-08-12 00:43:167144 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587145 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]038e9a32008-10-08 22:40:167146 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:167147}
[email protected]4ddaf2502008-10-23 18:26:197148
[email protected]ea9dc9a2009-09-05 00:43:327149// For the NTLM implementation using SSPI, we skip the NTLM tests since we
7150// can't hook into its internals to cause it to generate predictable NTLM
7151// authorization headers.
7152#if defined(NTLM_PORTABLE)
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377153// The NTLM authentication unit tests are based on known test data from the
7154// [MS-NLMP] Specification [1]. These tests are primarily of the authentication
7155// flow rather than the implementation of the NTLM protocol. See net/ntlm
7156// for the implementation and testing of the protocol.
7157//
7158// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
[email protected]385a4672009-03-11 22:21:297159
7160// Enter the correct password and authenticate successfully.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557161TEST_F(HttpNetworkTransactionTest, NTLMAuthV2) {
[email protected]1c773ea12009-04-28 19:58:427162 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:247163 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557164 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107165 request.traffic_annotation =
7166 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:547167
7168 // Ensure load is not disrupted by flags which suppress behaviour specific
7169 // to other auth schemes.
7170 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:247171
Zentaro Kavanagh6ccee512017-09-28 18:34:097172 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7173 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097174 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277175
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377176 // Generate the NTLM messages based on known test data.
7177 std::string negotiate_msg;
7178 std::string challenge_msg;
7179 std::string authenticate_msg;
7180 base::Base64Encode(
7181 base::StringPiece(
7182 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247183 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377184 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557185 base::Base64Encode(
7186 base::StringPiece(
7187 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247188 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557189 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377190 base::Base64Encode(
7191 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097192 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557193 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247194 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557195 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377196 &authenticate_msg);
7197
[email protected]3f918782009-02-28 01:29:247198 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557199 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7200 "Host: server\r\n"
7201 "Connection: keep-alive\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247202 };
7203
7204 MockRead data_reads1[] = {
7205 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047206 // Negotiate and NTLM are often requested together. However, we only want
7207 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7208 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:247209 MockRead("WWW-Authenticate: NTLM\r\n"),
7210 MockRead("Connection: close\r\n"),
7211 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367212 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247213 // Missing content -- won't matter, as connection will be reset.
[email protected]3f918782009-02-28 01:29:247214 };
7215
7216 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167217 // After restarting with a null identity, this is the
7218 // request we should be issuing -- the final header line contains a Type
7219 // 1 message.
7220 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557221 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167222 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377223 "Authorization: NTLM "),
7224 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247225
bnc691fda62016-08-12 00:43:167226 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377227 // (using correct credentials). The second request continues on the
7228 // same connection.
bnc691fda62016-08-12 00:43:167229 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557230 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167231 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377232 "Authorization: NTLM "),
7233 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:247234 };
7235
7236 MockRead data_reads2[] = {
Bence Béky1e4ef192017-09-18 19:58:027237 // The origin server responds with a Type 2 message.
7238 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377239 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7240 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027241 MockRead("Content-Type: text/html\r\n\r\n"),
7242 MockRead("You are not authorized to view this page\r\n"),
[email protected]3f918782009-02-28 01:29:247243
Bence Béky1e4ef192017-09-18 19:58:027244 // Lastly we get the desired content.
7245 MockRead("HTTP/1.1 200 OK\r\n"),
7246 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7247 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]3f918782009-02-28 01:29:247248 };
7249
Ryan Sleevib8d7ea02018-05-07 20:01:017250 StaticSocketDataProvider data1(data_reads1, data_writes1);
7251 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:077252 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7253 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:247254
Bence Béky83eb3512017-09-05 12:56:097255 SSLSocketDataProvider ssl1(ASYNC, OK);
7256 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7257 SSLSocketDataProvider ssl2(ASYNC, OK);
7258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7259
[email protected]49639fa2011-12-20 23:22:417260 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:247261
bnc691fda62016-08-12 00:43:167262 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507263
tfarina42834112016-09-22 13:38:207264 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017265 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247266
7267 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017268 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247269
bnc691fda62016-08-12 00:43:167270 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227271
bnc691fda62016-08-12 00:43:167272 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527273 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587274 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]3f918782009-02-28 01:29:247275
[email protected]49639fa2011-12-20 23:22:417276 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:257277
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377278 rv = trans.RestartWithAuth(
7279 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7280 callback2.callback());
robpercival214763f2016-07-01 23:27:017281 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257282
7283 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017284 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257285
bnc691fda62016-08-12 00:43:167286 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257287
bnc691fda62016-08-12 00:43:167288 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527289 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587290 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]10af5fe72011-01-31 16:17:257291
[email protected]49639fa2011-12-20 23:22:417292 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:247293
bnc691fda62016-08-12 00:43:167294 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017295 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:247296
[email protected]0757e7702009-03-27 04:00:227297 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017298 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:247299
bnc691fda62016-08-12 00:43:167300 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527301 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587302 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027303 EXPECT_EQ(14, response->headers->GetContentLength());
7304
7305 std::string response_data;
7306 rv = ReadTransaction(&trans, &response_data);
7307 EXPECT_THAT(rv, IsOk());
7308 EXPECT_EQ("Please Login\r\n", response_data);
7309
7310 EXPECT_TRUE(data1.AllReadDataConsumed());
7311 EXPECT_TRUE(data1.AllWriteDataConsumed());
7312 EXPECT_TRUE(data2.AllReadDataConsumed());
7313 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]3f918782009-02-28 01:29:247314}
7315
[email protected]385a4672009-03-11 22:21:297316// Enter a wrong password, and then the correct one.
Zentaro Kavanagh1890a3d2018-01-29 19:52:557317TEST_F(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
[email protected]1c773ea12009-04-28 19:58:427318 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:297319 request.method = "GET";
Zentaro Kavanagh1890a3d2018-01-29 19:52:557320 request.url = GURL("https://server/kids/login.aspx");
Ramin Halavatib5e433e62018-02-07 07:41:107321 request.traffic_annotation =
7322 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]385a4672009-03-11 22:21:297323
Zentaro Kavanagh6ccee512017-09-28 18:34:097324 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7325 MockGetMSTime, MockGenerateRandom, MockGetHostName);
danakj1fd259a02016-04-16 03:17:097326 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277327
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377328 // Generate the NTLM messages based on known test data.
7329 std::string negotiate_msg;
7330 std::string challenge_msg;
7331 std::string authenticate_msg;
7332 base::Base64Encode(
7333 base::StringPiece(
7334 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247335 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377336 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557337 base::Base64Encode(
7338 base::StringPiece(
7339 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247340 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557341 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377342 base::Base64Encode(
7343 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097344 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557345 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247346 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557347 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377348 &authenticate_msg);
7349
7350 // The authenticate message when |kWrongPassword| is sent.
7351 std::string wrong_password_authenticate_msg(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557352 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
7353 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
7354 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
7355 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
7356 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
7357 "QwBPAE0AUABVAFQARQBSAA==");
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377358
Zentaro Kavanagh1890a3d2018-01-29 19:52:557359 // Sanity check that it's the same length as the correct authenticate message
7360 // and that it's different.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377361 ASSERT_EQ(authenticate_msg.length(),
7362 wrong_password_authenticate_msg.length());
Zentaro Kavanagh1890a3d2018-01-29 19:52:557363 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377364
[email protected]385a4672009-03-11 22:21:297365 MockWrite data_writes1[] = {
Zentaro Kavanagh1890a3d2018-01-29 19:52:557366 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
7367 "Host: server\r\n"
7368 "Connection: keep-alive\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297369 };
7370
7371 MockRead data_reads1[] = {
7372 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:047373 // Negotiate and NTLM are often requested together. However, we only want
7374 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
7375 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:297376 MockRead("WWW-Authenticate: NTLM\r\n"),
7377 MockRead("Connection: close\r\n"),
7378 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:367379 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297380 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297381 };
7382
7383 MockWrite data_writes2[] = {
bnc691fda62016-08-12 00:43:167384 // After restarting with a null identity, this is the
7385 // request we should be issuing -- the final header line contains a Type
7386 // 1 message.
7387 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557388 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167389 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377390 "Authorization: NTLM "),
7391 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297392
bnc691fda62016-08-12 00:43:167393 // After calling trans.RestartWithAuth(), we should send a Type 3 message
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377394 // (using incorrect credentials). The second request continues on the
7395 // same connection.
bnc691fda62016-08-12 00:43:167396 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557397 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167398 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377399 "Authorization: NTLM "),
7400 MockWrite(wrong_password_authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297401 };
7402
7403 MockRead data_reads2[] = {
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377404 // The origin server responds with a Type 2 message.
7405 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7406 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7407 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
7408 MockRead("Content-Type: text/html\r\n\r\n"),
7409 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297410
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377411 // Wrong password.
7412 MockRead("HTTP/1.1 401 Access Denied\r\n"),
7413 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
7414 MockRead("Content-Length: 42\r\n"),
7415 MockRead("Content-Type: text/html\r\n\r\n"),
7416 // Missing content -- won't matter, as connection will be reset.
[email protected]385a4672009-03-11 22:21:297417 };
7418
7419 MockWrite data_writes3[] = {
bnc691fda62016-08-12 00:43:167420 // After restarting with a null identity, this is the
7421 // request we should be issuing -- the final header line contains a Type
7422 // 1 message.
7423 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557424 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167425 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377426 "Authorization: NTLM "),
7427 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297428
bnc691fda62016-08-12 00:43:167429 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7430 // (the credentials for the origin server). The second request continues
7431 // on the same connection.
7432 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557433 "Host: server\r\n"
bnc691fda62016-08-12 00:43:167434 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377435 "Authorization: NTLM "),
7436 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:297437 };
7438
7439 MockRead data_reads3[] = {
Bence Béky1e4ef192017-09-18 19:58:027440 // The origin server responds with a Type 2 message.
7441 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377442 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7443 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027444 MockRead("Content-Type: text/html\r\n\r\n"),
7445 MockRead("You are not authorized to view this page\r\n"),
[email protected]385a4672009-03-11 22:21:297446
Bence Béky1e4ef192017-09-18 19:58:027447 // Lastly we get the desired content.
7448 MockRead("HTTP/1.1 200 OK\r\n"),
7449 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
7450 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
[email protected]385a4672009-03-11 22:21:297451 };
7452
Ryan Sleevib8d7ea02018-05-07 20:01:017453 StaticSocketDataProvider data1(data_reads1, data_writes1);
7454 StaticSocketDataProvider data2(data_reads2, data_writes2);
7455 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:077456 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7457 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7458 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:297459
Bence Béky83eb3512017-09-05 12:56:097460 SSLSocketDataProvider ssl1(ASYNC, OK);
7461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7462 SSLSocketDataProvider ssl2(ASYNC, OK);
7463 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7464 SSLSocketDataProvider ssl3(ASYNC, OK);
7465 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7466
[email protected]49639fa2011-12-20 23:22:417467 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:297468
bnc691fda62016-08-12 00:43:167469 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:507470
tfarina42834112016-09-22 13:38:207471 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017472 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297473
7474 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017475 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297476
bnc691fda62016-08-12 00:43:167477 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:297478
bnc691fda62016-08-12 00:43:167479 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527480 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587481 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]385a4672009-03-11 22:21:297482
[email protected]49639fa2011-12-20 23:22:417483 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:297484
[email protected]0757e7702009-03-27 04:00:227485 // Enter the wrong password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377486 rv = trans.RestartWithAuth(
7487 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
7488 callback2.callback());
robpercival214763f2016-07-01 23:27:017489 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:297490
[email protected]10af5fe72011-01-31 16:17:257491 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017492 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:297493
bnc691fda62016-08-12 00:43:167494 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417495 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:167496 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:017497 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257498 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017499 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:167500 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:227501
bnc691fda62016-08-12 00:43:167502 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527503 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587504 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
[email protected]0757e7702009-03-27 04:00:227505
[email protected]49639fa2011-12-20 23:22:417506 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:227507
7508 // Now enter the right password.
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377509 rv = trans.RestartWithAuth(
7510 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7511 callback4.callback());
robpercival214763f2016-07-01 23:27:017512 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:257513
7514 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:017515 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:257516
bnc691fda62016-08-12 00:43:167517 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:257518
[email protected]49639fa2011-12-20 23:22:417519 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:257520
7521 // One more roundtrip
bnc691fda62016-08-12 00:43:167522 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:017523 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227524
7525 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:017526 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227527
bnc691fda62016-08-12 00:43:167528 response = trans.GetResponseInfo();
Emily Starkf2c9bbd2019-04-09 17:08:587529 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027530 EXPECT_EQ(14, response->headers->GetContentLength());
7531
7532 std::string response_data;
7533 rv = ReadTransaction(&trans, &response_data);
7534 EXPECT_THAT(rv, IsOk());
7535 EXPECT_EQ("Please Login\r\n", response_data);
7536
7537 EXPECT_TRUE(data1.AllReadDataConsumed());
7538 EXPECT_TRUE(data1.AllWriteDataConsumed());
7539 EXPECT_TRUE(data2.AllReadDataConsumed());
7540 EXPECT_TRUE(data2.AllWriteDataConsumed());
7541 EXPECT_TRUE(data3.AllReadDataConsumed());
7542 EXPECT_TRUE(data3.AllWriteDataConsumed());
[email protected]385a4672009-03-11 22:21:297543}
Bence Béky83eb3512017-09-05 12:56:097544
Bence Béky3238f2e12017-09-22 22:44:497545// Server requests NTLM authentication, which is not supported over HTTP/2.
7546// Subsequent request with authorization header should be sent over HTTP/1.1.
Bence Béky83eb3512017-09-05 12:56:097547TEST_F(HttpNetworkTransactionTest, NTLMOverHttp2) {
Zentaro Kavanagh6ccee512017-09-28 18:34:097548 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7549 MockGetMSTime, MockGenerateRandom, MockGetHostName);
Bence Béky83eb3512017-09-05 12:56:097550
Zentaro Kavanagh1890a3d2018-01-29 19:52:557551 const char* kUrl = "https://server/kids/login.aspx";
Bence Béky83eb3512017-09-05 12:56:097552
7553 HttpRequestInfo request;
7554 request.method = "GET";
7555 request.url = GURL(kUrl);
Ramin Halavatib5e433e62018-02-07 07:41:107556 request.traffic_annotation =
7557 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky83eb3512017-09-05 12:56:097558
7559 // First request without credentials.
Ryan Hamilton0239aac2018-05-19 00:03:137560 spdy::SpdyHeaderBlock request_headers0(
7561 spdy_util_.ConstructGetHeaderBlock(kUrl));
7562 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
Bence Béky83eb3512017-09-05 12:56:097563 1, std::move(request_headers0), LOWEST, true));
7564
Ryan Hamilton0239aac2018-05-19 00:03:137565 spdy::SpdyHeaderBlock response_headers0;
7566 response_headers0[spdy::kHttp2StatusHeader] = "401";
Bence Béky83eb3512017-09-05 12:56:097567 response_headers0["www-authenticate"] = "NTLM";
Ryan Hamilton0239aac2018-05-19 00:03:137568 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
Bence Béky83eb3512017-09-05 12:56:097569 1, std::move(response_headers0), true));
7570
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377571 // Stream 1 is closed.
7572 spdy_util_.UpdateWithStreamDestruction(1);
7573
7574 // Generate the NTLM messages based on known test data.
7575 std::string negotiate_msg;
7576 std::string challenge_msg;
7577 std::string authenticate_msg;
7578 base::Base64Encode(
7579 base::StringPiece(
7580 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247581 base::size(ntlm::test::kExpectedNegotiateMsg)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377582 &negotiate_msg);
Zentaro Kavanagh1890a3d2018-01-29 19:52:557583 base::Base64Encode(
7584 base::StringPiece(
7585 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247586 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
Zentaro Kavanagh1890a3d2018-01-29 19:52:557587 &challenge_msg);
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377588 base::Base64Encode(
7589 base::StringPiece(
Zentaro Kavanagh6ccee512017-09-28 18:34:097590 reinterpret_cast<const char*>(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557591 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247592 base::size(
Zentaro Kavanagh1890a3d2018-01-29 19:52:557593 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377594 &authenticate_msg);
7595
7596 // Retry with authorization header.
Ryan Hamilton0239aac2018-05-19 00:03:137597 spdy::SpdyHeaderBlock request_headers1(
7598 spdy_util_.ConstructGetHeaderBlock(kUrl));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377599 request_headers1["authorization"] = std::string("NTLM ") + negotiate_msg;
Ryan Hamilton0239aac2018-05-19 00:03:137600 spdy::SpdySerializedFrame request1(spdy_util_.ConstructSpdyHeaders(
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377601 3, std::move(request_headers1), LOWEST, true));
7602
Ryan Hamilton0239aac2018-05-19 00:03:137603 spdy::SpdySerializedFrame rst(
7604 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_HTTP_1_1_REQUIRED));
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377605
Bence Béky3238f2e12017-09-22 22:44:497606 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
7607 MockRead reads0[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)};
Bence Béky83eb3512017-09-05 12:56:097608
7609 // Retry yet again using HTTP/1.1.
7610 MockWrite writes1[] = {
7611 // After restarting with a null identity, this is the
7612 // request we should be issuing -- the final header line contains a Type
7613 // 1 message.
7614 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557615 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097616 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377617 "Authorization: NTLM "),
7618 MockWrite(negotiate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097619
7620 // After calling trans.RestartWithAuth(), we should send a Type 3 message
7621 // (the credentials for the origin server). The second request continues
7622 // on the same connection.
7623 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
Zentaro Kavanagh1890a3d2018-01-29 19:52:557624 "Host: server\r\n"
Bence Béky83eb3512017-09-05 12:56:097625 "Connection: keep-alive\r\n"
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377626 "Authorization: NTLM "),
7627 MockWrite(authenticate_msg.c_str()), MockWrite("\r\n\r\n"),
Bence Béky83eb3512017-09-05 12:56:097628 };
7629
7630 MockRead reads1[] = {
7631 // The origin server responds with a Type 2 message.
7632 MockRead("HTTP/1.1 401 Access Denied\r\n"),
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377633 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
7634 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
Bence Béky83eb3512017-09-05 12:56:097635 MockRead("Content-Type: text/html\r\n\r\n"),
7636 MockRead("You are not authorized to view this page\r\n"),
7637
7638 // Lastly we get the desired content.
7639 MockRead("HTTP/1.1 200 OK\r\n"),
7640 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
Bence Béky1e4ef192017-09-18 19:58:027641 MockRead("Content-Length: 14\r\n\r\n"), MockRead("Please Login\r\n"),
Bence Béky83eb3512017-09-05 12:56:097642 };
Ryan Sleevib8d7ea02018-05-07 20:01:017643 SequencedSocketData data0(reads0, writes0);
7644 StaticSocketDataProvider data1(reads1, writes1);
Bence Béky83eb3512017-09-05 12:56:097645 session_deps_.socket_factory->AddSocketDataProvider(&data0);
7646 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7647
7648 SSLSocketDataProvider ssl0(ASYNC, OK);
7649 ssl0.next_proto = kProtoHTTP2;
7650 SSLSocketDataProvider ssl1(ASYNC, OK);
7651 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
7652 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
7653
7654 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7655 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7656
7657 TestCompletionCallback callback1;
7658 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
7659 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7660
7661 rv = callback1.WaitForResult();
7662 EXPECT_THAT(rv, IsOk());
7663
7664 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7665
7666 const HttpResponseInfo* response = trans.GetResponseInfo();
7667 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587668 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
Bence Béky83eb3512017-09-05 12:56:097669
7670 TestCompletionCallback callback2;
7671
Zentaro Kavanagh5b27a6e22017-09-25 23:00:377672 rv = trans.RestartWithAuth(
7673 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7674 callback2.callback());
Bence Béky83eb3512017-09-05 12:56:097675 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7676
7677 rv = callback2.WaitForResult();
7678 EXPECT_THAT(rv, IsOk());
7679
7680 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7681
7682 response = trans.GetResponseInfo();
7683 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587684 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky83eb3512017-09-05 12:56:097685
7686 TestCompletionCallback callback3;
7687
7688 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
7689 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7690
7691 rv = callback3.WaitForResult();
7692 EXPECT_THAT(rv, IsOk());
7693
7694 response = trans.GetResponseInfo();
7695 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587696 EXPECT_FALSE(response->auth_challenge.has_value());
Bence Béky1e4ef192017-09-18 19:58:027697 EXPECT_EQ(14, response->headers->GetContentLength());
7698
7699 std::string response_data;
7700 rv = ReadTransaction(&trans, &response_data);
7701 EXPECT_THAT(rv, IsOk());
7702 EXPECT_EQ("Please Login\r\n", response_data);
7703
7704 EXPECT_TRUE(data0.AllReadDataConsumed());
7705 EXPECT_TRUE(data0.AllWriteDataConsumed());
7706 EXPECT_TRUE(data1.AllReadDataConsumed());
7707 EXPECT_TRUE(data1.AllWriteDataConsumed());
Bence Béky83eb3512017-09-05 12:56:097708}
David Benjamin5cb91132018-04-06 05:54:497709
7710// Test that, if we have an NTLM proxy and the origin resets the connection, we
7711// do no retry forever checking for TLS version interference. This is a
David Benjamind61bd532019-04-23 21:11:377712// regression test for https://crbug.com/823387. The version interference probe
7713// has since been removed, but retain the regression test so we can update it if
7714// we add future TLS retries.
David Benjamin5cb91132018-04-06 05:54:497715TEST_F(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
7716 // The NTLM test data expects the proxy to be named 'server'. The origin is
7717 // https://origin/.
7718 session_deps_.proxy_resolution_service =
7719 ProxyResolutionService::CreateFixedFromPacResult(
7720 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
7721
7722 SSLConfig config;
David Benjamin5cb91132018-04-06 05:54:497723 session_deps_.ssl_config_service =
Ryan Sleevib8449e02018-07-15 04:31:077724 std::make_unique<TestSSLConfigService>(config);
David Benjamin5cb91132018-04-06 05:54:497725
7726 HttpRequestInfo request;
7727 request.method = "GET";
7728 request.url = GURL("https://origin/");
7729 request.traffic_annotation =
7730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7731
7732 // Ensure load is not disrupted by flags which suppress behaviour specific
7733 // to other auth schemes.
7734 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
7735
7736 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(
7737 MockGetMSTime, MockGenerateRandom, MockGetHostName);
7738 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7739
7740 // Generate the NTLM messages based on known test data.
7741 std::string negotiate_msg;
7742 std::string challenge_msg;
7743 std::string authenticate_msg;
7744 base::Base64Encode(
7745 base::StringPiece(
7746 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
Avi Drissman4365a4782018-12-28 19:26:247747 base::size(ntlm::test::kExpectedNegotiateMsg)),
David Benjamin5cb91132018-04-06 05:54:497748 &negotiate_msg);
7749 base::Base64Encode(
7750 base::StringPiece(
7751 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
Avi Drissman4365a4782018-12-28 19:26:247752 base::size(ntlm::test::kChallengeMsgFromSpecV2)),
David Benjamin5cb91132018-04-06 05:54:497753 &challenge_msg);
7754 base::Base64Encode(
7755 base::StringPiece(
7756 reinterpret_cast<const char*>(
7757 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
Avi Drissman4365a4782018-12-28 19:26:247758 base::size(
David Benjamin5cb91132018-04-06 05:54:497759 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)),
7760 &authenticate_msg);
7761
7762 MockWrite data_writes[] = {
7763 // The initial CONNECT request.
7764 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7765 "Host: origin:443\r\n"
7766 "Proxy-Connection: keep-alive\r\n\r\n"),
7767
7768 // After restarting with an identity.
7769 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7770 "Host: origin:443\r\n"
7771 "Proxy-Connection: keep-alive\r\n"
7772 "Proxy-Authorization: NTLM "),
7773 MockWrite(negotiate_msg.c_str()),
7774 // End headers.
7775 MockWrite("\r\n\r\n"),
7776
7777 // The second restart.
7778 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
7779 "Host: origin:443\r\n"
7780 "Proxy-Connection: keep-alive\r\n"
7781 "Proxy-Authorization: NTLM "),
7782 MockWrite(authenticate_msg.c_str()),
7783 // End headers.
7784 MockWrite("\r\n\r\n"),
7785 };
7786
7787 MockRead data_reads[] = {
7788 // The initial NTLM response.
7789 MockRead("HTTP/1.1 407 Access Denied\r\n"
7790 "Content-Length: 0\r\n"
7791 "Proxy-Authenticate: NTLM\r\n\r\n"),
7792
7793 // The NTLM challenge message.
7794 MockRead("HTTP/1.1 407 Access Denied\r\n"
7795 "Content-Length: 0\r\n"
7796 "Proxy-Authenticate: NTLM "),
7797 MockRead(challenge_msg.c_str()),
7798 // End headers.
7799 MockRead("\r\n\r\n"),
7800
7801 // Finally the tunnel is established.
7802 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
7803 };
7804
Ryan Sleevib8d7ea02018-05-07 20:01:017805 StaticSocketDataProvider data(data_reads, data_writes);
David Benjamin5cb91132018-04-06 05:54:497806 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
David Benjamin5cb91132018-04-06 05:54:497807 session_deps_.socket_factory->AddSocketDataProvider(&data);
7808 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
David Benjamin5cb91132018-04-06 05:54:497809
7810 // Start the transaction. The proxy responds with an NTLM authentication
7811 // request.
7812 TestCompletionCallback callback;
7813 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7814 int rv = callback.GetResult(
7815 trans.Start(&request, callback.callback(), NetLogWithSource()));
7816
7817 EXPECT_THAT(rv, IsOk());
7818 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
7819 const HttpResponseInfo* response = trans.GetResponseInfo();
7820 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587821 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
David Benjamin5cb91132018-04-06 05:54:497822
David Benjamind61bd532019-04-23 21:11:377823 // Configure credentials and restart. The proxy responds with the challenge
7824 // message.
David Benjamin5cb91132018-04-06 05:54:497825 rv = callback.GetResult(trans.RestartWithAuth(
7826 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
7827 callback.callback()));
7828 EXPECT_THAT(rv, IsOk());
7829 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
7830 response = trans.GetResponseInfo();
7831 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:587832 EXPECT_FALSE(response->auth_challenge.has_value());
David Benjamin5cb91132018-04-06 05:54:497833
David Benjamind61bd532019-04-23 21:11:377834 // Restart once more. The tunnel will be established and then the SSL
7835 // handshake will reset.
David Benjamin5cb91132018-04-06 05:54:497836 rv = callback.GetResult(
7837 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
7838 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
7839}
7840
[email protected]ea9dc9a2009-09-05 00:43:327841#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:297842
[email protected]4ddaf2502008-10-23 18:26:197843// Test reading a server response which has only headers, and no body.
7844// After some maximum number of bytes is consumed, the transaction should
7845// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:017846TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:427847 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:197848 request.method = "GET";
bncce36dca22015-04-21 22:11:237849 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107850 request.traffic_annotation =
7851 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]4ddaf2502008-10-23 18:26:197852
danakj1fd259a02016-04-16 03:17:097853 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:167854 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277855
[email protected]b75b7b2f2009-10-06 00:54:537856 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:437857 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:537858 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:197859
7860 MockRead data_reads[] = {
7861 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:067862 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:197863 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:067864 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:197865 };
Ryan Sleevib8d7ea02018-05-07 20:01:017866 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077867 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:197868
[email protected]49639fa2011-12-20 23:22:417869 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:197870
tfarina42834112016-09-22 13:38:207871 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017872 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:197873
7874 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017875 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:197876}
[email protected]f4e426b2008-11-05 00:24:497877
7878// Make sure that we don't try to reuse a TCPClientSocket when failing to
7879// establish tunnel.
7880// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:017881TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:277882 HttpRequestInfo request;
7883 request.method = "GET";
bncce36dca22015-04-21 22:11:237884 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107885 request.traffic_annotation =
7886 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:277887
[email protected]f4e426b2008-11-05 00:24:497888 // Configure against proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:497889 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
7890 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]db8f44c2008-12-13 04:52:017891
danakj1fd259a02016-04-16 03:17:097892 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:497893
bnc87dcefc2017-05-25 12:47:587894 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:197895 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]f4e426b2008-11-05 00:24:497896
[email protected]f4e426b2008-11-05 00:24:497897 // Since we have proxy, should try to establish tunnel.
7898 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:177899 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7900 "Host: www.example.org:443\r\n"
7901 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:497902 };
7903
[email protected]77848d12008-11-14 00:00:227904 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:497905 // connection. Usually a proxy would return 501 (not implemented),
7906 // or 200 (tunnel established).
7907 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:237908 MockRead("HTTP/1.1 404 Not Found\r\n"),
7909 MockRead("Content-Length: 10\r\n\r\n"),
7910 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:497911 };
7912
Ryan Sleevib8d7ea02018-05-07 20:01:017913 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:077914 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:497915
[email protected]49639fa2011-12-20 23:22:417916 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:497917
tfarina42834112016-09-22 13:38:207918 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017919 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:497920
7921 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017922 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:497923
[email protected]b4404c02009-04-10 16:38:527924 // Empty the current queue. This is necessary because idle sockets are
7925 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557926 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:527927
[email protected]f4e426b2008-11-05 00:24:497928 // We now check to make sure the TCPClientSocket was not added back to
7929 // the pool.
[email protected]90499482013-06-01 00:39:507930 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497931 trans.reset();
fdoray92e35a72016-06-10 15:54:557932 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:497933 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:507934 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:497935}
[email protected]372d34a2008-11-05 21:30:517936
[email protected]1b157c02009-04-21 01:55:407937// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:017938TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:427939 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:407940 request.method = "GET";
bncce36dca22015-04-21 22:11:237941 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107942 request.traffic_annotation =
7943 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1b157c02009-04-21 01:55:407944
danakj1fd259a02016-04-16 03:17:097945 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:277946
bnc691fda62016-08-12 00:43:167947 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:277948
[email protected]1b157c02009-04-21 01:55:407949 MockRead data_reads[] = {
7950 // A part of the response body is received with the response headers.
7951 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
7952 // The rest of the response body is received in two parts.
7953 MockRead("lo"),
7954 MockRead(" world"),
7955 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:067956 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:407957 };
7958
Ryan Sleevib8d7ea02018-05-07 20:01:017959 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:077960 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:407961
[email protected]49639fa2011-12-20 23:22:417962 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:407963
tfarina42834112016-09-22 13:38:207964 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:017965 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:407966
7967 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017968 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407969
bnc691fda62016-08-12 00:43:167970 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:527971 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:407972
wezca1070932016-05-26 20:30:527973 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:407974 std::string status_line = response->headers->GetStatusLine();
7975 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
7976
[email protected]90499482013-06-01 00:39:507977 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407978
7979 std::string response_data;
bnc691fda62016-08-12 00:43:167980 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:017981 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:407982 EXPECT_EQ("hello world", response_data);
7983
7984 // Empty the current queue. This is necessary because idle sockets are
7985 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:557986 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:407987
7988 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:507989 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:407990}
7991
[email protected]76a505b2010-08-25 06:23:007992// Make sure that we recycle a SSL socket after reading all of the response
7993// body.
bncd16676a2016-07-20 16:23:017994TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:007995 HttpRequestInfo request;
7996 request.method = "GET";
bncce36dca22015-04-21 22:11:237997 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:107998 request.traffic_annotation =
7999 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008000
8001 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238002 MockWrite(
8003 "GET / HTTP/1.1\r\n"
8004 "Host: www.example.org\r\n"
8005 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008006 };
8007
8008 MockRead data_reads[] = {
8009 MockRead("HTTP/1.1 200 OK\r\n"),
8010 MockRead("Content-Length: 11\r\n\r\n"),
8011 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068012 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008013 };
8014
[email protected]8ddf8322012-02-23 18:08:068015 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078016 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:008017
Ryan Sleevib8d7ea02018-05-07 20:01:018018 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078019 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:008020
[email protected]49639fa2011-12-20 23:22:418021 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008022
danakj1fd259a02016-04-16 03:17:098023 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168024 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008025
tfarina42834112016-09-22 13:38:208026 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008027
robpercival214763f2016-07-01 23:27:018028 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8029 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008030
bnc691fda62016-08-12 00:43:168031 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528032 ASSERT_TRUE(response);
8033 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008034 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8035
[email protected]90499482013-06-01 00:39:508036 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008037
8038 std::string response_data;
bnc691fda62016-08-12 00:43:168039 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018040 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008041 EXPECT_EQ("hello world", response_data);
8042
8043 // Empty the current queue. This is necessary because idle sockets are
8044 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558045 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008046
8047 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238048 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008049}
8050
8051// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
8052// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:018053TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:008054 HttpRequestInfo request;
8055 request.method = "GET";
bncce36dca22015-04-21 22:11:238056 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:108057 request.traffic_annotation =
8058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:008059
8060 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238061 MockWrite(
8062 "GET / HTTP/1.1\r\n"
8063 "Host: www.example.org\r\n"
8064 "Connection: keep-alive\r\n\r\n"),
8065 MockWrite(
8066 "GET / HTTP/1.1\r\n"
8067 "Host: www.example.org\r\n"
8068 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:008069 };
8070
8071 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:428072 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8073 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:008074
[email protected]8ddf8322012-02-23 18:08:068075 SSLSocketDataProvider ssl(ASYNC, OK);
8076 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078077 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8078 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:008079
Ryan Sleevib8d7ea02018-05-07 20:01:018080 StaticSocketDataProvider data(data_reads, data_writes);
8081 StaticSocketDataProvider data2(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:078082 session_deps_.socket_factory->AddSocketDataProvider(&data);
8083 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:008084
[email protected]49639fa2011-12-20 23:22:418085 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:008086
danakj1fd259a02016-04-16 03:17:098087 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:588088 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:198089 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008090
tfarina42834112016-09-22 13:38:208091 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008092
robpercival214763f2016-07-01 23:27:018093 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8094 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008095
8096 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528097 ASSERT_TRUE(response);
8098 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008099 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8100
[email protected]90499482013-06-01 00:39:508101 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008102
8103 std::string response_data;
8104 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018105 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008106 EXPECT_EQ("hello world", response_data);
8107
8108 // Empty the current queue. This is necessary because idle sockets are
8109 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558110 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008111
8112 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238113 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008114
8115 // Now start the second transaction, which should reuse the previous socket.
8116
bnc87dcefc2017-05-25 12:47:588117 trans =
Jeremy Roman0579ed62017-08-29 15:56:198118 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]76a505b2010-08-25 06:23:008119
tfarina42834112016-09-22 13:38:208120 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
[email protected]76a505b2010-08-25 06:23:008121
robpercival214763f2016-07-01 23:27:018122 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8123 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:008124
8125 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528126 ASSERT_TRUE(response);
8127 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:008128 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8129
[email protected]90499482013-06-01 00:39:508130 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008131
8132 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018133 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:008134 EXPECT_EQ("hello world", response_data);
8135
8136 // Empty the current queue. This is necessary because idle sockets are
8137 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558138 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:008139
8140 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238141 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:008142}
8143
maksim.sisov0adf8592016-07-15 06:25:568144// Grab a socket, use it, and put it back into the pool. Then, make
8145// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018146TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568147 HttpRequestInfo request;
8148 request.method = "GET";
8149 request.url = GURL("http://www.example.org/");
8150 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108151 request.traffic_annotation =
8152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568153
8154 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8155
bnc691fda62016-08-12 00:43:168156 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568157
8158 MockRead data_reads[] = {
8159 // A part of the response body is received with the response headers.
8160 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8161 // The rest of the response body is received in two parts.
8162 MockRead("lo"), MockRead(" world"),
8163 MockRead("junk"), // Should not be read!!
8164 MockRead(SYNCHRONOUS, OK),
8165 };
8166
Ryan Sleevib8d7ea02018-05-07 20:01:018167 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
maksim.sisov0adf8592016-07-15 06:25:568168 session_deps_.socket_factory->AddSocketDataProvider(&data);
8169
8170 TestCompletionCallback callback;
8171
tfarina42834112016-09-22 13:38:208172 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568173 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8174
8175 EXPECT_THAT(callback.GetResult(rv), IsOk());
8176
bnc691fda62016-08-12 00:43:168177 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568178 ASSERT_TRUE(response);
8179 EXPECT_TRUE(response->headers);
8180 std::string status_line = response->headers->GetStatusLine();
8181 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8182
8183 // Make memory critical notification and ensure the transaction still has been
8184 // operating right.
8185 base::MemoryPressureListener::NotifyMemoryPressure(
8186 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8187 base::RunLoop().RunUntilIdle();
8188
8189 // Socket should not be flushed as long as it is not idle.
8190 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8191
8192 std::string response_data;
bnc691fda62016-08-12 00:43:168193 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568194 EXPECT_THAT(rv, IsOk());
8195 EXPECT_EQ("hello world", response_data);
8196
8197 // Empty the current queue. This is necessary because idle sockets are
8198 // added to the connection pool asynchronously with a PostTask.
8199 base::RunLoop().RunUntilIdle();
8200
8201 // We now check to make sure the socket was added back to the pool.
8202 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8203
8204 // Idle sockets should be flushed now.
8205 base::MemoryPressureListener::NotifyMemoryPressure(
8206 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8207 base::RunLoop().RunUntilIdle();
8208
8209 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8210}
8211
yucliu48f235d2018-01-11 00:59:558212// Disable idle socket closing on memory pressure.
8213// Grab a socket, use it, and put it back into the pool. Then, make
8214// low memory notification and ensure the socket pool is NOT flushed.
8215TEST_F(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
8216 HttpRequestInfo request;
8217 request.method = "GET";
8218 request.url = GURL("http://www.example.org/");
8219 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108220 request.traffic_annotation =
8221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
yucliu48f235d2018-01-11 00:59:558222
8223 // Disable idle socket closing on memory pressure.
8224 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
8225 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8226
8227 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8228
8229 MockRead data_reads[] = {
8230 // A part of the response body is received with the response headers.
8231 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
8232 // The rest of the response body is received in two parts.
8233 MockRead("lo"), MockRead(" world"),
8234 MockRead("junk"), // Should not be read!!
8235 MockRead(SYNCHRONOUS, OK),
8236 };
8237
Ryan Sleevib8d7ea02018-05-07 20:01:018238 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
yucliu48f235d2018-01-11 00:59:558239 session_deps_.socket_factory->AddSocketDataProvider(&data);
8240
8241 TestCompletionCallback callback;
8242
8243 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
8244 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8245
8246 EXPECT_THAT(callback.GetResult(rv), IsOk());
8247
8248 const HttpResponseInfo* response = trans.GetResponseInfo();
8249 ASSERT_TRUE(response);
8250 EXPECT_TRUE(response->headers);
8251 std::string status_line = response->headers->GetStatusLine();
8252 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
8253
8254 // Make memory critical notification and ensure the transaction still has been
8255 // operating right.
8256 base::MemoryPressureListener::NotifyMemoryPressure(
8257 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8258 base::RunLoop().RunUntilIdle();
8259
8260 // Socket should not be flushed as long as it is not idle.
8261 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
8262
8263 std::string response_data;
8264 rv = ReadTransaction(&trans, &response_data);
8265 EXPECT_THAT(rv, IsOk());
8266 EXPECT_EQ("hello world", response_data);
8267
8268 // Empty the current queue. This is necessary because idle sockets are
8269 // added to the connection pool asynchronously with a PostTask.
8270 base::RunLoop().RunUntilIdle();
8271
8272 // We now check to make sure the socket was added back to the pool.
8273 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8274
8275 // Idle sockets should NOT be flushed on moderate memory pressure.
8276 base::MemoryPressureListener::NotifyMemoryPressure(
8277 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
8278 base::RunLoop().RunUntilIdle();
8279
8280 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8281
8282 // Idle sockets should NOT be flushed on critical memory pressure.
8283 base::MemoryPressureListener::NotifyMemoryPressure(
8284 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8285 base::RunLoop().RunUntilIdle();
8286
8287 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
8288}
8289
maksim.sisov0adf8592016-07-15 06:25:568290// Grab an SSL socket, use it, and put it back into the pool. Then, make
8291// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:018292TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:568293 HttpRequestInfo request;
8294 request.method = "GET";
8295 request.url = GURL("https://www.example.org/");
8296 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108297 request.traffic_annotation =
8298 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
maksim.sisov0adf8592016-07-15 06:25:568299
8300 MockWrite data_writes[] = {
8301 MockWrite("GET / HTTP/1.1\r\n"
8302 "Host: www.example.org\r\n"
8303 "Connection: keep-alive\r\n\r\n"),
8304 };
8305
8306 MockRead data_reads[] = {
8307 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
8308 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
8309
8310 SSLSocketDataProvider ssl(ASYNC, OK);
8311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8312
Ryan Sleevib8d7ea02018-05-07 20:01:018313 StaticSocketDataProvider data(data_reads, data_writes);
maksim.sisov0adf8592016-07-15 06:25:568314 session_deps_.socket_factory->AddSocketDataProvider(&data);
8315
8316 TestCompletionCallback callback;
8317
8318 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168319 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
maksim.sisov0adf8592016-07-15 06:25:568320
Matt Menke9d5e2c92019-02-05 01:42:238321 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
tfarina42834112016-09-22 13:38:208322 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
maksim.sisov0adf8592016-07-15 06:25:568323
8324 EXPECT_THAT(callback.GetResult(rv), IsOk());
8325
bnc691fda62016-08-12 00:43:168326 const HttpResponseInfo* response = trans.GetResponseInfo();
maksim.sisov0adf8592016-07-15 06:25:568327 ASSERT_TRUE(response);
8328 ASSERT_TRUE(response->headers);
8329 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8330
8331 // Make memory critical notification and ensure the transaction still has been
8332 // operating right.
8333 base::MemoryPressureListener::NotifyMemoryPressure(
8334 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8335 base::RunLoop().RunUntilIdle();
8336
Matt Menke9d5e2c92019-02-05 01:42:238337 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568338
8339 std::string response_data;
bnc691fda62016-08-12 00:43:168340 rv = ReadTransaction(&trans, &response_data);
maksim.sisov0adf8592016-07-15 06:25:568341 EXPECT_THAT(rv, IsOk());
8342 EXPECT_EQ("hello world", response_data);
8343
8344 // Empty the current queue. This is necessary because idle sockets are
8345 // added to the connection pool asynchronously with a PostTask.
8346 base::RunLoop().RunUntilIdle();
8347
8348 // We now check to make sure the socket was added back to the pool.
Matt Menke9d5e2c92019-02-05 01:42:238349 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568350
8351 // Make memory notification once again and ensure idle socket is closed.
8352 base::MemoryPressureListener::NotifyMemoryPressure(
8353 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
8354 base::RunLoop().RunUntilIdle();
8355
Matt Menke9d5e2c92019-02-05 01:42:238356 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
maksim.sisov0adf8592016-07-15 06:25:568357}
8358
[email protected]b4404c02009-04-10 16:38:528359// Make sure that we recycle a socket after a zero-length response.
8360// http://crbug.com/9880
bncd16676a2016-07-20 16:23:018361TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:428362 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:528363 request.method = "GET";
bncce36dca22015-04-21 22:11:238364 request.url = GURL(
8365 "http://www.example.org/csi?v=3&s=web&action=&"
8366 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
8367 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
8368 "rt=prt.2642,ol.2649,xjs.2951");
Ramin Halavatib5e433e62018-02-07 07:41:108369 request.traffic_annotation =
8370 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b4404c02009-04-10 16:38:528371
danakj1fd259a02016-04-16 03:17:098372 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:278373
[email protected]b4404c02009-04-10 16:38:528374 MockRead data_reads[] = {
8375 MockRead("HTTP/1.1 204 No Content\r\n"
8376 "Content-Length: 0\r\n"
8377 "Content-Type: text/html\r\n\r\n"),
8378 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:068379 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:528380 };
8381
Ryan Sleevib8d7ea02018-05-07 20:01:018382 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:078383 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:528384
mmenkecc2298e2015-12-07 18:20:188385 // Transaction must be created after the MockReads, so it's destroyed before
8386 // them.
bnc691fda62016-08-12 00:43:168387 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
mmenkecc2298e2015-12-07 18:20:188388
[email protected]49639fa2011-12-20 23:22:418389 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:528390
tfarina42834112016-09-22 13:38:208391 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018392 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:528393
8394 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018395 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528396
bnc691fda62016-08-12 00:43:168397 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528398 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:528399
wezca1070932016-05-26 20:30:528400 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:528401 std::string status_line = response->headers->GetStatusLine();
8402 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
8403
[email protected]90499482013-06-01 00:39:508404 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528405
8406 std::string response_data;
bnc691fda62016-08-12 00:43:168407 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018408 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:528409 EXPECT_EQ("", response_data);
8410
8411 // Empty the current queue. This is necessary because idle sockets are
8412 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:558413 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:528414
8415 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:508416 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:528417}
8418
bncd16676a2016-07-20 16:23:018419TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:098420 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:228421 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:198422 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:228423 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:278424
[email protected]1c773ea12009-04-28 19:58:428425 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:518426 // Transaction 1: a GET request that succeeds. The socket is recycled
8427 // after use.
8428 request[0].method = "GET";
8429 request[0].url = GURL("http://www.google.com/");
8430 request[0].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108431 request[0].traffic_annotation =
8432 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518433 // Transaction 2: a POST request. Reuses the socket kept alive from
8434 // transaction 1. The first attempts fails when writing the POST data.
8435 // This causes the transaction to retry with a new socket. The second
8436 // attempt succeeds.
8437 request[1].method = "POST";
8438 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:278439 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:518440 request[1].load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:108441 request[1].traffic_annotation =
8442 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]372d34a2008-11-05 21:30:518443
danakj1fd259a02016-04-16 03:17:098444 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:518445
8446 // The first socket is used for transaction 1 and the first attempt of
8447 // transaction 2.
8448
8449 // The response of transaction 1.
8450 MockRead data_reads1[] = {
8451 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
8452 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068453 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518454 };
8455 // The mock write results of transaction 1 and the first attempt of
8456 // transaction 2.
8457 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:068458 MockWrite(SYNCHRONOUS, 64), // GET
8459 MockWrite(SYNCHRONOUS, 93), // POST
8460 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:518461 };
Ryan Sleevib8d7ea02018-05-07 20:01:018462 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:518463
8464 // The second socket is used for the second attempt of transaction 2.
8465
8466 // The response of transaction 2.
8467 MockRead data_reads2[] = {
8468 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
8469 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:068470 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:518471 };
8472 // The mock write results of the second attempt of transaction 2.
8473 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:068474 MockWrite(SYNCHRONOUS, 93), // POST
8475 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:518476 };
Ryan Sleevib8d7ea02018-05-07 20:01:018477 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:518478
[email protected]bb88e1d32013-05-03 23:11:078479 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8480 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:518481
thestig9d3bb0c2015-01-24 00:49:518482 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:518483 "hello world", "welcome"
8484 };
8485
8486 for (int i = 0; i < 2; ++i) {
bnc691fda62016-08-12 00:43:168487 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]372d34a2008-11-05 21:30:518488
[email protected]49639fa2011-12-20 23:22:418489 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:518490
tfarina42834112016-09-22 13:38:208491 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018492 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:518493
8494 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018495 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518496
bnc691fda62016-08-12 00:43:168497 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528498 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:518499
wezca1070932016-05-26 20:30:528500 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:518501 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8502
8503 std::string response_data;
bnc691fda62016-08-12 00:43:168504 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:018505 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:518506 EXPECT_EQ(kExpectedResponseData[i], response_data);
8507 }
8508}
[email protected]f9ee6b52008-11-08 06:46:238509
8510// Test the request-challenge-retry sequence for basic auth when there is
8511// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:168512// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:018513TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:428514 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238515 request.method = "GET";
bncce36dca22015-04-21 22:11:238516 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:418517 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108518 request.traffic_annotation =
8519 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]a97cca42009-08-14 01:00:298520
danakj1fd259a02016-04-16 03:17:098521 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168522 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278523
[email protected]a97cca42009-08-14 01:00:298524 // The password contains an escaped character -- for this test to pass it
8525 // will need to be unescaped by HttpNetworkTransaction.
8526 EXPECT_EQ("b%40r", request.url.password());
8527
[email protected]f9ee6b52008-11-08 06:46:238528 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238529 MockWrite(
8530 "GET / HTTP/1.1\r\n"
8531 "Host: www.example.org\r\n"
8532 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238533 };
8534
8535 MockRead data_reads1[] = {
8536 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8537 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8538 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068539 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238540 };
8541
[email protected]2262e3a2012-05-22 16:08:168542 // After the challenge above, the transaction will be restarted using the
8543 // identity from the url (foo, b@r) to answer the challenge.
8544 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238545 MockWrite(
8546 "GET / HTTP/1.1\r\n"
8547 "Host: www.example.org\r\n"
8548 "Connection: keep-alive\r\n"
8549 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168550 };
8551
8552 MockRead data_reads2[] = {
8553 MockRead("HTTP/1.0 200 OK\r\n"),
8554 MockRead("Content-Length: 100\r\n\r\n"),
8555 MockRead(SYNCHRONOUS, OK),
8556 };
8557
Ryan Sleevib8d7ea02018-05-07 20:01:018558 StaticSocketDataProvider data1(data_reads1, data_writes1);
8559 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078560 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8561 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238562
[email protected]49639fa2011-12-20 23:22:418563 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208564 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018565 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238566 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018567 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168568 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168569
8570 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168571 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018572 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168573 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018574 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168575 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:228576
bnc691fda62016-08-12 00:43:168577 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528578 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168579
8580 // There is no challenge info, since the identity in URL worked.
Emily Starkf2c9bbd2019-04-09 17:08:588581 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168582
8583 EXPECT_EQ(100, response->headers->GetContentLength());
8584
8585 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558586 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:168587}
8588
8589// Test the request-challenge-retry sequence for basic auth when there is an
8590// incorrect identity in the URL. The identity from the URL should be used only
8591// once.
bncd16676a2016-07-20 16:23:018592TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:168593 HttpRequestInfo request;
8594 request.method = "GET";
8595 // Note: the URL has a username:password in it. The password "baz" is
8596 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:238597 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:168598
8599 request.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:108600 request.traffic_annotation =
8601 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2262e3a2012-05-22 16:08:168602
danakj1fd259a02016-04-16 03:17:098603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168604 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2262e3a2012-05-22 16:08:168605
8606 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238607 MockWrite(
8608 "GET / HTTP/1.1\r\n"
8609 "Host: www.example.org\r\n"
8610 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168611 };
8612
8613 MockRead data_reads1[] = {
8614 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8615 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8616 MockRead("Content-Length: 10\r\n\r\n"),
8617 MockRead(SYNCHRONOUS, ERR_FAILED),
8618 };
8619
8620 // After the challenge above, the transaction will be restarted using the
8621 // identity from the url (foo, baz) to answer the challenge.
8622 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238623 MockWrite(
8624 "GET / HTTP/1.1\r\n"
8625 "Host: www.example.org\r\n"
8626 "Connection: keep-alive\r\n"
8627 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168628 };
8629
8630 MockRead data_reads2[] = {
8631 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8632 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8633 MockRead("Content-Length: 10\r\n\r\n"),
8634 MockRead(SYNCHRONOUS, ERR_FAILED),
8635 };
8636
8637 // After the challenge above, the transaction will be restarted using the
8638 // identity supplied by the user (foo, bar) to answer the challenge.
8639 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238640 MockWrite(
8641 "GET / HTTP/1.1\r\n"
8642 "Host: www.example.org\r\n"
8643 "Connection: keep-alive\r\n"
8644 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:168645 };
8646
8647 MockRead data_reads3[] = {
8648 MockRead("HTTP/1.0 200 OK\r\n"),
8649 MockRead("Content-Length: 100\r\n\r\n"),
8650 MockRead(SYNCHRONOUS, OK),
8651 };
8652
Ryan Sleevib8d7ea02018-05-07 20:01:018653 StaticSocketDataProvider data1(data_reads1, data_writes1);
8654 StaticSocketDataProvider data2(data_reads2, data_writes2);
8655 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:078656 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8657 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8658 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:168659
8660 TestCompletionCallback callback1;
8661
tfarina42834112016-09-22 13:38:208662 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018663 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168664
8665 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018666 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:168667
bnc691fda62016-08-12 00:43:168668 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168669 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:168670 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:018671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168672 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018673 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168674 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168675
bnc691fda62016-08-12 00:43:168676 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528677 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588678 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2262e3a2012-05-22 16:08:168679
8680 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168681 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018682 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:168683 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018684 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168685 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2262e3a2012-05-22 16:08:168686
bnc691fda62016-08-12 00:43:168687 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528688 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:168689
8690 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588691 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2262e3a2012-05-22 16:08:168692
8693 EXPECT_EQ(100, response->headers->GetContentLength());
8694
[email protected]ea9dc9a2009-09-05 00:43:328695 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558696 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:328697}
8698
[email protected]2217aa22013-10-11 03:03:548699
8700// Test the request-challenge-retry sequence for basic auth when there is a
8701// correct identity in the URL, but its use is being suppressed. The identity
8702// from the URL should never be used.
bncd16676a2016-07-20 16:23:018703TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:548704 HttpRequestInfo request;
8705 request.method = "GET";
bncce36dca22015-04-21 22:11:238706 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:548707 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
Ramin Halavatib5e433e62018-02-07 07:41:108708 request.traffic_annotation =
8709 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2217aa22013-10-11 03:03:548710
danakj1fd259a02016-04-16 03:17:098711 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:168712 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2217aa22013-10-11 03:03:548713
8714 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238715 MockWrite(
8716 "GET / HTTP/1.1\r\n"
8717 "Host: www.example.org\r\n"
8718 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548719 };
8720
8721 MockRead data_reads1[] = {
8722 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8723 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8724 MockRead("Content-Length: 10\r\n\r\n"),
8725 MockRead(SYNCHRONOUS, ERR_FAILED),
8726 };
8727
8728 // After the challenge above, the transaction will be restarted using the
8729 // identity supplied by the user, not the one in the URL, to answer the
8730 // challenge.
8731 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:238732 MockWrite(
8733 "GET / HTTP/1.1\r\n"
8734 "Host: www.example.org\r\n"
8735 "Connection: keep-alive\r\n"
8736 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:548737 };
8738
8739 MockRead data_reads3[] = {
8740 MockRead("HTTP/1.0 200 OK\r\n"),
8741 MockRead("Content-Length: 100\r\n\r\n"),
8742 MockRead(SYNCHRONOUS, OK),
8743 };
8744
Ryan Sleevib8d7ea02018-05-07 20:01:018745 StaticSocketDataProvider data1(data_reads1, data_writes1);
8746 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]2217aa22013-10-11 03:03:548747 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8748 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8749
8750 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:208751 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018752 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548753 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018754 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168755 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548756
bnc691fda62016-08-12 00:43:168757 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528758 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588759 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]2217aa22013-10-11 03:03:548760
8761 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:168762 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:018763 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:548764 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:018765 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:168766 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]2217aa22013-10-11 03:03:548767
bnc691fda62016-08-12 00:43:168768 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528769 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:548770
8771 // There is no challenge info, since the identity worked.
Emily Starkf2c9bbd2019-04-09 17:08:588772 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]2217aa22013-10-11 03:03:548773 EXPECT_EQ(100, response->headers->GetContentLength());
8774
8775 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:558776 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:548777}
8778
[email protected]f9ee6b52008-11-08 06:46:238779// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:018780TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:098781 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:238782
8783 // Transaction 1: authenticate (foo, bar) on MyRealm1
8784 {
[email protected]1c773ea12009-04-28 19:58:428785 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238786 request.method = "GET";
bncce36dca22015-04-21 22:11:238787 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:108788 request.traffic_annotation =
8789 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238790
bnc691fda62016-08-12 00:43:168791 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278792
[email protected]f9ee6b52008-11-08 06:46:238793 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238794 MockWrite(
8795 "GET /x/y/z HTTP/1.1\r\n"
8796 "Host: www.example.org\r\n"
8797 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238798 };
8799
8800 MockRead data_reads1[] = {
8801 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8802 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8803 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068804 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238805 };
8806
8807 // Resend with authorization (username=foo, password=bar)
8808 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238809 MockWrite(
8810 "GET /x/y/z HTTP/1.1\r\n"
8811 "Host: www.example.org\r\n"
8812 "Connection: keep-alive\r\n"
8813 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238814 };
8815
8816 // Sever accepts the authorization.
8817 MockRead data_reads2[] = {
8818 MockRead("HTTP/1.0 200 OK\r\n"),
8819 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068820 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238821 };
8822
Ryan Sleevib8d7ea02018-05-07 20:01:018823 StaticSocketDataProvider data1(data_reads1, data_writes1);
8824 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078825 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8826 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238827
[email protected]49639fa2011-12-20 23:22:418828 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238829
tfarina42834112016-09-22 13:38:208830 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018831 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238832
8833 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018834 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238835
bnc691fda62016-08-12 00:43:168836 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528837 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588838 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:238839
[email protected]49639fa2011-12-20 23:22:418840 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238841
bnc691fda62016-08-12 00:43:168842 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
8843 callback2.callback());
robpercival214763f2016-07-01 23:27:018844 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238845
8846 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018847 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238848
bnc691fda62016-08-12 00:43:168849 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528850 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588851 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238852 EXPECT_EQ(100, response->headers->GetContentLength());
8853 }
8854
8855 // ------------------------------------------------------------------------
8856
8857 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
8858 {
[email protected]1c773ea12009-04-28 19:58:428859 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238860 request.method = "GET";
8861 // Note that Transaction 1 was at /x/y/z, so this is in the same
8862 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:238863 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:108864 request.traffic_annotation =
8865 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238866
bnc691fda62016-08-12 00:43:168867 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278868
[email protected]f9ee6b52008-11-08 06:46:238869 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238870 MockWrite(
8871 "GET /x/y/a/b HTTP/1.1\r\n"
8872 "Host: www.example.org\r\n"
8873 "Connection: keep-alive\r\n"
8874 // Send preemptive authorization for MyRealm1
8875 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238876 };
8877
8878 // The server didn't like the preemptive authorization, and
8879 // challenges us for a different realm (MyRealm2).
8880 MockRead data_reads1[] = {
8881 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
8882 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
8883 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068884 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:238885 };
8886
8887 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
8888 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:238889 MockWrite(
8890 "GET /x/y/a/b HTTP/1.1\r\n"
8891 "Host: www.example.org\r\n"
8892 "Connection: keep-alive\r\n"
8893 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238894 };
8895
8896 // Sever accepts the authorization.
8897 MockRead data_reads2[] = {
8898 MockRead("HTTP/1.0 200 OK\r\n"),
8899 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068900 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238901 };
8902
Ryan Sleevib8d7ea02018-05-07 20:01:018903 StaticSocketDataProvider data1(data_reads1, data_writes1);
8904 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:078905 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8906 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:238907
[email protected]49639fa2011-12-20 23:22:418908 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238909
tfarina42834112016-09-22 13:38:208910 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018911 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238912
8913 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018914 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238915
bnc691fda62016-08-12 00:43:168916 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528917 ASSERT_TRUE(response);
8918 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:048919 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:438920 EXPECT_EQ("http://www.example.org",
8921 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:048922 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:198923 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:238924
[email protected]49639fa2011-12-20 23:22:418925 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:238926
bnc691fda62016-08-12 00:43:168927 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
8928 callback2.callback());
robpercival214763f2016-07-01 23:27:018929 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238930
8931 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:018932 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238933
bnc691fda62016-08-12 00:43:168934 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528935 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:588936 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238937 EXPECT_EQ(100, response->headers->GetContentLength());
8938 }
8939
8940 // ------------------------------------------------------------------------
8941
8942 // Transaction 3: Resend a request in MyRealm's protection space --
8943 // succeed with preemptive authorization.
8944 {
[email protected]1c773ea12009-04-28 19:58:428945 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238946 request.method = "GET";
bncce36dca22015-04-21 22:11:238947 request.url = GURL("http://www.example.org/x/y/z2");
Ramin Halavatib5e433e62018-02-07 07:41:108948 request.traffic_annotation =
8949 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238950
bnc691fda62016-08-12 00:43:168951 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:278952
[email protected]f9ee6b52008-11-08 06:46:238953 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:238954 MockWrite(
8955 "GET /x/y/z2 HTTP/1.1\r\n"
8956 "Host: www.example.org\r\n"
8957 "Connection: keep-alive\r\n"
8958 // The authorization for MyRealm1 gets sent preemptively
8959 // (since the url is in the same protection space)
8960 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:238961 };
8962
8963 // Sever accepts the preemptive authorization
8964 MockRead data_reads1[] = {
8965 MockRead("HTTP/1.0 200 OK\r\n"),
8966 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068967 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:238968 };
8969
Ryan Sleevib8d7ea02018-05-07 20:01:018970 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:078971 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:238972
[email protected]49639fa2011-12-20 23:22:418973 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:238974
tfarina42834112016-09-22 13:38:208975 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:018976 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:238977
8978 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:018979 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:238980
bnc691fda62016-08-12 00:43:168981 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:528982 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:238983
Emily Starkf2c9bbd2019-04-09 17:08:588984 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:238985 EXPECT_EQ(100, response->headers->GetContentLength());
8986 }
8987
8988 // ------------------------------------------------------------------------
8989
8990 // Transaction 4: request another URL in MyRealm (however the
8991 // url is not known to belong to the protection space, so no pre-auth).
8992 {
[email protected]1c773ea12009-04-28 19:58:428993 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:238994 request.method = "GET";
bncce36dca22015-04-21 22:11:238995 request.url = GURL("http://www.example.org/x/1");
Ramin Halavatib5e433e62018-02-07 07:41:108996 request.traffic_annotation =
8997 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:238998
bnc691fda62016-08-12 00:43:168999 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279000
[email protected]f9ee6b52008-11-08 06:46:239001 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239002 MockWrite(
9003 "GET /x/1 HTTP/1.1\r\n"
9004 "Host: www.example.org\r\n"
9005 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239006 };
9007
9008 MockRead data_reads1[] = {
9009 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9010 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9011 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069012 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239013 };
9014
9015 // Resend with authorization from MyRealm's cache.
9016 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239017 MockWrite(
9018 "GET /x/1 HTTP/1.1\r\n"
9019 "Host: www.example.org\r\n"
9020 "Connection: keep-alive\r\n"
9021 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239022 };
9023
9024 // Sever accepts the authorization.
9025 MockRead data_reads2[] = {
9026 MockRead("HTTP/1.0 200 OK\r\n"),
9027 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069028 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239029 };
9030
Ryan Sleevib8d7ea02018-05-07 20:01:019031 StaticSocketDataProvider data1(data_reads1, data_writes1);
9032 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079033 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9034 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:239035
[email protected]49639fa2011-12-20 23:22:419036 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239037
tfarina42834112016-09-22 13:38:209038 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019039 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239040
9041 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019042 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239043
bnc691fda62016-08-12 00:43:169044 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419045 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169046 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019047 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229048 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019049 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169050 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229051
bnc691fda62016-08-12 00:43:169052 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529053 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589054 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239055 EXPECT_EQ(100, response->headers->GetContentLength());
9056 }
9057
9058 // ------------------------------------------------------------------------
9059
9060 // Transaction 5: request a URL in MyRealm, but the server rejects the
9061 // cached identity. Should invalidate and re-prompt.
9062 {
[email protected]1c773ea12009-04-28 19:58:429063 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:239064 request.method = "GET";
bncce36dca22015-04-21 22:11:239065 request.url = GURL("http://www.example.org/p/q/t");
Ramin Halavatib5e433e62018-02-07 07:41:109066 request.traffic_annotation =
9067 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]f9ee6b52008-11-08 06:46:239068
bnc691fda62016-08-12 00:43:169069 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279070
[email protected]f9ee6b52008-11-08 06:46:239071 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239072 MockWrite(
9073 "GET /p/q/t HTTP/1.1\r\n"
9074 "Host: www.example.org\r\n"
9075 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239076 };
9077
9078 MockRead data_reads1[] = {
9079 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9080 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9081 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069082 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239083 };
9084
9085 // Resend with authorization from cache for MyRealm.
9086 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239087 MockWrite(
9088 "GET /p/q/t HTTP/1.1\r\n"
9089 "Host: www.example.org\r\n"
9090 "Connection: keep-alive\r\n"
9091 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239092 };
9093
9094 // Sever rejects the authorization.
9095 MockRead data_reads2[] = {
9096 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9097 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9098 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069099 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:239100 };
9101
9102 // At this point we should prompt for new credentials for MyRealm.
9103 // Restart with username=foo3, password=foo4.
9104 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239105 MockWrite(
9106 "GET /p/q/t HTTP/1.1\r\n"
9107 "Host: www.example.org\r\n"
9108 "Connection: keep-alive\r\n"
9109 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:239110 };
9111
9112 // Sever accepts the authorization.
9113 MockRead data_reads3[] = {
9114 MockRead("HTTP/1.0 200 OK\r\n"),
9115 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069116 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:239117 };
9118
Ryan Sleevib8d7ea02018-05-07 20:01:019119 StaticSocketDataProvider data1(data_reads1, data_writes1);
9120 StaticSocketDataProvider data2(data_reads2, data_writes2);
9121 StaticSocketDataProvider data3(data_reads3, data_writes3);
[email protected]bb88e1d32013-05-03 23:11:079122 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9123 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9124 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:239125
[email protected]49639fa2011-12-20 23:22:419126 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:239127
tfarina42834112016-09-22 13:38:209128 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019129 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239130
9131 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019132 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239133
bnc691fda62016-08-12 00:43:169134 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:419135 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:169136 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:019137 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:229138 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019139 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169140 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]0757e7702009-03-27 04:00:229141
bnc691fda62016-08-12 00:43:169142 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529143 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589144 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]f9ee6b52008-11-08 06:46:239145
[email protected]49639fa2011-12-20 23:22:419146 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:239147
bnc691fda62016-08-12 00:43:169148 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
9149 callback3.callback());
robpercival214763f2016-07-01 23:27:019150 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:239151
[email protected]0757e7702009-03-27 04:00:229152 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019153 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:239154
bnc691fda62016-08-12 00:43:169155 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529156 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589157 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]f9ee6b52008-11-08 06:46:239158 EXPECT_EQ(100, response->headers->GetContentLength());
9159 }
9160}
[email protected]89ceba9a2009-03-21 03:46:069161
[email protected]3c32c5f2010-05-18 15:18:129162// Tests that nonce count increments when multiple auth attempts
9163// are started with the same nonce.
bncd16676a2016-07-20 16:23:019164TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:449165 HttpAuthHandlerDigest::Factory* digest_factory =
9166 new HttpAuthHandlerDigest::Factory();
9167 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
9168 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
9169 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:079170 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:099171 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:129172
9173 // Transaction 1: authenticate (foo, bar) on MyRealm1
9174 {
[email protected]3c32c5f2010-05-18 15:18:129175 HttpRequestInfo request;
9176 request.method = "GET";
bncce36dca22015-04-21 22:11:239177 request.url = GURL("http://www.example.org/x/y/z");
Ramin Halavatib5e433e62018-02-07 07:41:109178 request.traffic_annotation =
9179 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129180
bnc691fda62016-08-12 00:43:169181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279182
[email protected]3c32c5f2010-05-18 15:18:129183 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239184 MockWrite(
9185 "GET /x/y/z HTTP/1.1\r\n"
9186 "Host: www.example.org\r\n"
9187 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129188 };
9189
9190 MockRead data_reads1[] = {
9191 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
9192 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
9193 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069194 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129195 };
9196
9197 // Resend with authorization (username=foo, password=bar)
9198 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239199 MockWrite(
9200 "GET /x/y/z HTTP/1.1\r\n"
9201 "Host: www.example.org\r\n"
9202 "Connection: keep-alive\r\n"
9203 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9204 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
9205 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
9206 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129207 };
9208
9209 // Sever accepts the authorization.
9210 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:089211 MockRead("HTTP/1.0 200 OK\r\n"),
9212 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129213 };
9214
Ryan Sleevib8d7ea02018-05-07 20:01:019215 StaticSocketDataProvider data1(data_reads1, data_writes1);
9216 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:079217 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9218 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:129219
[email protected]49639fa2011-12-20 23:22:419220 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129221
tfarina42834112016-09-22 13:38:209222 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019223 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129224
9225 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019226 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129227
bnc691fda62016-08-12 00:43:169228 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529229 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589230 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
[email protected]3c32c5f2010-05-18 15:18:129231
[email protected]49639fa2011-12-20 23:22:419232 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:129233
bnc691fda62016-08-12 00:43:169234 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
9235 callback2.callback());
robpercival214763f2016-07-01 23:27:019236 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129237
9238 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019239 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129240
bnc691fda62016-08-12 00:43:169241 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529242 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589243 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129244 }
9245
9246 // ------------------------------------------------------------------------
9247
9248 // Transaction 2: Request another resource in digestive's protection space.
9249 // This will preemptively add an Authorization header which should have an
9250 // "nc" value of 2 (as compared to 1 in the first use.
9251 {
[email protected]3c32c5f2010-05-18 15:18:129252 HttpRequestInfo request;
9253 request.method = "GET";
9254 // Note that Transaction 1 was at /x/y/z, so this is in the same
9255 // protection space as digest.
bncce36dca22015-04-21 22:11:239256 request.url = GURL("http://www.example.org/x/y/a/b");
Ramin Halavatib5e433e62018-02-07 07:41:109257 request.traffic_annotation =
9258 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3c32c5f2010-05-18 15:18:129259
bnc691fda62016-08-12 00:43:169260 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279261
[email protected]3c32c5f2010-05-18 15:18:129262 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239263 MockWrite(
9264 "GET /x/y/a/b HTTP/1.1\r\n"
9265 "Host: www.example.org\r\n"
9266 "Connection: keep-alive\r\n"
9267 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
9268 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
9269 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
9270 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:129271 };
9272
9273 // Sever accepts the authorization.
9274 MockRead data_reads1[] = {
9275 MockRead("HTTP/1.0 200 OK\r\n"),
9276 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069277 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:129278 };
9279
Ryan Sleevib8d7ea02018-05-07 20:01:019280 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:079281 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:129282
[email protected]49639fa2011-12-20 23:22:419283 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:129284
tfarina42834112016-09-22 13:38:209285 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019286 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:129287
9288 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019289 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:129290
bnc691fda62016-08-12 00:43:169291 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:529292 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:589293 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]3c32c5f2010-05-18 15:18:129294 }
9295}
9296
[email protected]89ceba9a2009-03-21 03:46:069297// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:019298TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:069299 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:099300 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169301 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]89ceba9a2009-03-21 03:46:069302
9303 // Setup some state (which we expect ResetStateForRestart() will clear).
Victor Costan9c7302b2018-08-27 16:39:449304 trans.read_buf_ = base::MakeRefCounted<IOBuffer>(15);
bnc691fda62016-08-12 00:43:169305 trans.read_buf_len_ = 15;
9306 trans.request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:069307
9308 // Setup state in response_
bnc691fda62016-08-12 00:43:169309 HttpResponseInfo* response = &trans.response_;
Emily Starkf2c9bbd2019-04-09 17:08:589310 response->auth_challenge = base::nullopt;
[email protected]70d66502011-09-23 00:55:089311 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:579312 response->response_time = base::Time::Now();
9313 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:069314
9315 { // Setup state for response_.vary_data
9316 HttpRequestInfo request;
9317 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
9318 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:279319 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:439320 request.extra_headers.SetHeader("Foo", "1");
9321 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:509322 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:069323 }
9324
9325 // Cause the above state to be reset.
bnc691fda62016-08-12 00:43:169326 trans.ResetStateForRestart();
[email protected]89ceba9a2009-03-21 03:46:069327
9328 // Verify that the state that needed to be reset, has been reset.
bnc691fda62016-08-12 00:43:169329 EXPECT_FALSE(trans.read_buf_);
9330 EXPECT_EQ(0, trans.read_buf_len_);
9331 EXPECT_TRUE(trans.request_headers_.IsEmpty());
Emily Starkf2c9bbd2019-04-09 17:08:589332 EXPECT_FALSE(response->auth_challenge.has_value());
wezca1070932016-05-26 20:30:529333 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:049334 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:089335 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:579336 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:069337}
9338
[email protected]bacff652009-03-31 17:50:339339// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:019340TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:339341 HttpRequestInfo request;
9342 request.method = "GET";
bncce36dca22015-04-21 22:11:239343 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109344 request.traffic_annotation =
9345 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339346
danakj1fd259a02016-04-16 03:17:099347 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169348 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:279349
[email protected]bacff652009-03-31 17:50:339350 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:239351 MockWrite(
9352 "GET / HTTP/1.1\r\n"
9353 "Host: www.example.org\r\n"
9354 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339355 };
9356
9357 MockRead data_reads[] = {
9358 MockRead("HTTP/1.0 200 OK\r\n"),
9359 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9360 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069361 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339362 };
9363
[email protected]5ecc992a42009-11-11 01:41:599364 StaticSocketDataProvider ssl_bad_certificate;
Ryan Sleevib8d7ea02018-05-07 20:01:019365 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069366 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9367 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339368
[email protected]bb88e1d32013-05-03 23:11:079369 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9370 session_deps_.socket_factory->AddSocketDataProvider(&data);
9371 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9372 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339373
[email protected]49639fa2011-12-20 23:22:419374 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339375
tfarina42834112016-09-22 13:38:209376 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019377 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339378
9379 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019380 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339381
bnc691fda62016-08-12 00:43:169382 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019383 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339384
9385 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019386 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339387
bnc691fda62016-08-12 00:43:169388 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339389
wezca1070932016-05-26 20:30:529390 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339391 EXPECT_EQ(100, response->headers->GetContentLength());
9392}
9393
9394// Test HTTPS connections to a site with a bad certificate, going through a
9395// proxy
bncd16676a2016-07-20 16:23:019396TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499397 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9398 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339399
9400 HttpRequestInfo request;
9401 request.method = "GET";
bncce36dca22015-04-21 22:11:239402 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109403 request.traffic_annotation =
9404 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]bacff652009-03-31 17:50:339405
9406 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:179407 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9408 "Host: www.example.org:443\r\n"
9409 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339410 };
9411
9412 MockRead proxy_reads[] = {
9413 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069414 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:339415 };
9416
9417 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179418 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9419 "Host: www.example.org:443\r\n"
9420 "Proxy-Connection: keep-alive\r\n\r\n"),
9421 MockWrite("GET / HTTP/1.1\r\n"
9422 "Host: www.example.org\r\n"
9423 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:339424 };
9425
9426 MockRead data_reads[] = {
9427 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9428 MockRead("HTTP/1.0 200 OK\r\n"),
9429 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9430 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069431 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:339432 };
9433
Ryan Sleevib8d7ea02018-05-07 20:01:019434 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
9435 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069436 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
9437 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:339438
[email protected]bb88e1d32013-05-03 23:11:079439 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
9440 session_deps_.socket_factory->AddSocketDataProvider(&data);
9441 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
9442 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:339443
[email protected]49639fa2011-12-20 23:22:419444 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:339445
9446 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:079447 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:339448
danakj1fd259a02016-04-16 03:17:099449 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169450 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bacff652009-03-31 17:50:339451
tfarina42834112016-09-22 13:38:209452 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019453 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339454
9455 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019456 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:339457
bnc691fda62016-08-12 00:43:169458 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:019459 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:339460
9461 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019462 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:339463
bnc691fda62016-08-12 00:43:169464 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]bacff652009-03-31 17:50:339465
wezca1070932016-05-26 20:30:529466 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:339467 EXPECT_EQ(100, response->headers->GetContentLength());
9468 }
9469}
9470
[email protected]2df19bb2010-08-25 20:13:469471
9472// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:019473TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599474 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499475 ProxyResolutionService::CreateFixedFromPacResult(
9476 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519477 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079478 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:469479
9480 HttpRequestInfo request;
9481 request.method = "GET";
bncce36dca22015-04-21 22:11:239482 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109483 request.traffic_annotation =
9484 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:469485
9486 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179487 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9488 "Host: www.example.org:443\r\n"
9489 "Proxy-Connection: keep-alive\r\n\r\n"),
9490 MockWrite("GET / HTTP/1.1\r\n"
9491 "Host: www.example.org\r\n"
9492 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:469493 };
9494
9495 MockRead data_reads[] = {
9496 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
9497 MockRead("HTTP/1.1 200 OK\r\n"),
9498 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9499 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069500 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:469501 };
9502
Ryan Sleevib8d7ea02018-05-07 20:01:019503 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069504 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9505 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:469506
[email protected]bb88e1d32013-05-03 23:11:079507 session_deps_.socket_factory->AddSocketDataProvider(&data);
9508 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9509 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:469510
[email protected]49639fa2011-12-20 23:22:419511 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:469512
danakj1fd259a02016-04-16 03:17:099513 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169514 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:469515
tfarina42834112016-09-22 13:38:209516 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019517 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:469518
9519 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019520 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:169521 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:469522
wezca1070932016-05-26 20:30:529523 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:469524
tbansal2ecbbc72016-10-06 17:15:479525 EXPECT_TRUE(response->proxy_server.is_https());
[email protected]2df19bb2010-08-25 20:13:469526 EXPECT_TRUE(response->headers->IsKeepAlive());
9527 EXPECT_EQ(200, response->headers->response_code());
9528 EXPECT_EQ(100, response->headers->GetContentLength());
9529 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:209530
9531 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:169532 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:209533 TestLoadTimingNotReusedWithPac(load_timing_info,
9534 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:469535}
9536
Eric Roman695a7872019-04-16 21:53:299537// Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
bncd16676a2016-07-20 16:23:019538TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
Lily Houghton8c2f97d2018-01-22 05:06:599539 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499540 ProxyResolutionService::CreateFixedFromPacResult(
9541 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519542 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:079543 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:299544
Matt Menkeecfecfc72019-02-05 19:15:289545 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9546 session_deps_.host_resolver->set_ondemand_mode(true);
9547
[email protected]511f6f52010-12-17 03:58:299548 HttpRequestInfo request;
Eric Roman74103c72019-02-21 00:23:129549 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
[email protected]511f6f52010-12-17 03:58:299550 request.method = "GET";
bncce36dca22015-04-21 22:11:239551 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109552 request.traffic_annotation =
9553 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299554
9555 MockWrite data_writes[] = {
Matt Menkeecfecfc72019-02-05 19:15:289556 MockWrite(ASYNC, 0,
9557 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:179558 "Host: www.example.org:443\r\n"
9559 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299560 };
9561
9562 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289563 // Pause on first read.
9564 MockRead(ASYNC, ERR_IO_PENDING, 1),
9565 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
9566 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
9567 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299568 };
9569
Matt Menkeecfecfc72019-02-05 19:15:289570 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069571 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299572
[email protected]bb88e1d32013-05-03 23:11:079573 session_deps_.socket_factory->AddSocketDataProvider(&data);
9574 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299575
[email protected]49639fa2011-12-20 23:22:419576 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299577
danakj1fd259a02016-04-16 03:17:099578 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169579 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299580
tfarina42834112016-09-22 13:38:209581 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019582 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289583 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
9584
9585 // Host resolution takes |kTimeIncrement|.
9586 FastForwardBy(kTimeIncrement);
9587 // Resolving the current request with |ResolveNow| will cause the pending
9588 // request to instantly complete, and the async connect will start as well.
9589 session_deps_.host_resolver->ResolveOnlyRequestNow();
9590
9591 // Connecting takes |kTimeIncrement|.
9592 FastForwardBy(kTimeIncrement);
9593 data.RunUntilPaused();
9594
9595 // The server takes |kTimeIncrement| to respond.
9596 FastForwardBy(kTimeIncrement);
9597 data.Resume();
[email protected]511f6f52010-12-17 03:58:299598
9599 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599600 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299601}
9602
Eric Roman74103c72019-02-21 00:23:129603// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
9604TEST_F(HttpNetworkTransactionTest,
9605 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
9606 base::HistogramTester histograms;
9607 session_deps_.proxy_resolution_service =
9608 ProxyResolutionService::CreateFixedFromPacResult(
9609 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9610 TestNetLog net_log;
9611 session_deps_.net_log = &net_log;
9612
9613 HttpRequestInfo request;
9614 request.method = "GET";
9615 request.url = GURL("https://www.example.org/");
9616 request.traffic_annotation =
9617 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9618
9619 MockWrite data_writes[] = {
9620 MockWrite(ASYNC, 0,
9621 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9622 "Host: www.example.org:443\r\n"
9623 "Proxy-Connection: keep-alive\r\n\r\n"),
9624 };
9625
9626 MockRead data_reads[] = {
9627 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9628 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9629 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9630 };
9631
9632 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9633 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9634
9635 session_deps_.socket_factory->AddSocketDataProvider(&data);
9636 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9637
9638 TestCompletionCallback callback;
9639
9640 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9641 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9642
9643 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9644 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9645
9646 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599647 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129648}
9649
9650// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
9651// request for main frames.
9652TEST_F(HttpNetworkTransactionTest,
9653 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
9654 base::HistogramTester histograms;
9655 session_deps_.proxy_resolution_service =
9656 ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
9657 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9658 TestNetLog net_log;
9659 session_deps_.net_log = &net_log;
9660
9661 HttpRequestInfo request;
9662 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
9663 request.method = "GET";
9664 request.url = GURL("https://www.example.org/");
9665 request.traffic_annotation =
9666 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9667
9668 MockWrite data_writes[] = {
9669 MockWrite(ASYNC, 0,
9670 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9671 "Host: www.example.org:443\r\n"
9672 "Proxy-Connection: keep-alive\r\n\r\n"),
9673 };
9674
9675 MockRead data_reads[] = {
9676 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
9677 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
9678 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
9679 };
9680
9681 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
9682 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
9683
9684 session_deps_.socket_factory->AddSocketDataProvider(&data);
9685 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
9686
9687 TestCompletionCallback callback;
9688
9689 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9690 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9691
9692 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
9693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9694
9695 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599696 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
Eric Roman74103c72019-02-21 00:23:129697}
9698
Eric Roman695a7872019-04-16 21:53:299699// Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
Eric Roman74103c72019-02-21 00:23:129700// frames.
bncd16676a2016-07-20 16:23:019701TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
Eric Roman74103c72019-02-21 00:23:129702 base::HistogramTester histograms;
Ramin Halavatica8d5252018-03-12 05:33:499703 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9704 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Matt Menkeecfecfc72019-02-05 19:15:289705 TestNetLog net_log;
9706 session_deps_.net_log = &net_log;
9707
Matt Menkeecfecfc72019-02-05 19:15:289708 const base::TimeDelta kTimeIncrement = base::TimeDelta::FromSeconds(4);
9709 session_deps_.host_resolver->set_ondemand_mode(true);
[email protected]511f6f52010-12-17 03:58:299710
9711 HttpRequestInfo request;
9712 request.method = "GET";
Eric Roman74103c72019-02-21 00:23:129713 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
bncce36dca22015-04-21 22:11:239714 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109715 request.traffic_annotation =
9716 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299717
Ryan Hamilton0239aac2018-05-19 00:03:139718 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049719 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9720 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139721 spdy::SpdySerializedFrame goaway(
9722 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299723 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419724 CreateMockWrite(conn, 0, SYNCHRONOUS),
Matt Menkeecfecfc72019-02-05 19:15:289725 CreateMockWrite(goaway, 3, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:299726 };
9727
9728 static const char* const kExtraHeaders[] = {
9729 "location",
9730 "http://login.example.com/",
9731 };
Ryan Hamilton0239aac2018-05-19 00:03:139732 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249733 "302", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:299734 MockRead data_reads[] = {
Matt Menkeecfecfc72019-02-05 19:15:289735 // Pause on first read.
9736 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
9737 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299738 };
9739
Matt Menkeecfecfc72019-02-05 19:15:289740 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069741 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369742 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299743
[email protected]bb88e1d32013-05-03 23:11:079744 session_deps_.socket_factory->AddSocketDataProvider(&data);
9745 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299746
[email protected]49639fa2011-12-20 23:22:419747 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299748
danakj1fd259a02016-04-16 03:17:099749 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169750 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299751
tfarina42834112016-09-22 13:38:209752 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019753 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Matt Menkeecfecfc72019-02-05 19:15:289754 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
[email protected]511f6f52010-12-17 03:58:299755
Matt Menkeecfecfc72019-02-05 19:15:289756 // Host resolution takes |kTimeIncrement|.
9757 FastForwardBy(kTimeIncrement);
9758 // Resolving the current request with |ResolveNow| will cause the pending
9759 // request to instantly complete, and the async connect will start as well.
9760 session_deps_.host_resolver->ResolveOnlyRequestNow();
9761
9762 // Connecting takes |kTimeIncrement|.
9763 FastForwardBy(kTimeIncrement);
9764 data.RunUntilPaused();
9765
9766 FastForwardBy(kTimeIncrement);
9767 data.Resume();
[email protected]511f6f52010-12-17 03:58:299768 rv = callback.WaitForResult();
Eric Roman96c5b292019-04-23 18:04:599769 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299770}
9771
[email protected]4eddbc732012-08-09 05:40:179772// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019773TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499774 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9775 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299776
9777 HttpRequestInfo request;
9778 request.method = "GET";
bncce36dca22015-04-21 22:11:239779 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109780 request.traffic_annotation =
9781 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299782
9783 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:179784 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
9785 "Host: www.example.org:443\r\n"
9786 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:299787 };
9788
9789 MockRead data_reads[] = {
9790 MockRead("HTTP/1.1 404 Not Found\r\n"),
9791 MockRead("Content-Length: 23\r\n\r\n"),
9792 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:069793 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:299794 };
9795
Ryan Sleevib8d7ea02018-05-07 20:01:019796 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069797 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:299798
[email protected]bb88e1d32013-05-03 23:11:079799 session_deps_.socket_factory->AddSocketDataProvider(&data);
9800 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299801
[email protected]49639fa2011-12-20 23:22:419802 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299803
danakj1fd259a02016-04-16 03:17:099804 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169805 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299806
tfarina42834112016-09-22 13:38:209807 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019808 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299809
9810 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019811 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299812
ttuttle960fcbf2016-04-19 13:26:329813 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299814}
9815
[email protected]4eddbc732012-08-09 05:40:179816// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:019817TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
Ramin Halavatica8d5252018-03-12 05:33:499818 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
9819 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299820
9821 HttpRequestInfo request;
9822 request.method = "GET";
bncce36dca22015-04-21 22:11:239823 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:109824 request.traffic_annotation =
9825 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]511f6f52010-12-17 03:58:299826
Ryan Hamilton0239aac2018-05-19 00:03:139827 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049828 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9829 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139830 spdy::SpdySerializedFrame rst(
9831 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
[email protected]511f6f52010-12-17 03:58:299832 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:419833 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:299834 };
9835
9836 static const char* const kExtraHeaders[] = {
9837 "location",
9838 "http://login.example.com/",
9839 };
Ryan Hamilton0239aac2018-05-19 00:03:139840 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249841 "404", kExtraHeaders, base::size(kExtraHeaders) / 2, 1));
Ryan Hamilton0239aac2018-05-19 00:03:139842 spdy::SpdySerializedFrame body(
Bence Békyd74f4382018-02-20 18:26:199843 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
[email protected]511f6f52010-12-17 03:58:299844 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:419845 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:139846 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:299847 };
9848
Ryan Sleevib8d7ea02018-05-07 20:01:019849 SequencedSocketData data(data_reads, data_writes);
[email protected]8ddf8322012-02-23 18:08:069850 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:369851 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:299852
[email protected]bb88e1d32013-05-03 23:11:079853 session_deps_.socket_factory->AddSocketDataProvider(&data);
9854 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:299855
[email protected]49639fa2011-12-20 23:22:419856 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:299857
danakj1fd259a02016-04-16 03:17:099858 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:169859 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]511f6f52010-12-17 03:58:299860
tfarina42834112016-09-22 13:38:209861 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:019862 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:299863
9864 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019865 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:299866
ttuttle960fcbf2016-04-19 13:26:329867 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:299868}
9869
[email protected]0c5fb722012-02-28 11:50:359870// Test the request-challenge-retry sequence for basic auth, through
9871// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:019872TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:359873 HttpRequestInfo request;
9874 request.method = "GET";
bncce36dca22015-04-21 22:11:239875 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:359876 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:299877 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
Ramin Halavatib5e433e62018-02-07 07:41:109878 request.traffic_annotation =
9879 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0c5fb722012-02-28 11:50:359880
9881 // Configure against https proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:599882 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:499883 ProxyResolutionService::CreateFixedFromPacResult(
9884 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:519885 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:079886 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:099887 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:359888
9889 // Since we have proxy, should try to establish tunnel.
Ryan Hamilton0239aac2018-05-19 00:03:139890 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049891 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9892 HostPortPair("www.example.org", 443)));
Ryan Hamilton0239aac2018-05-19 00:03:139893 spdy::SpdySerializedFrame rst(
9894 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
rdsmithebb50aa2015-11-12 03:44:389895 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:359896
bnc691fda62016-08-12 00:43:169897 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0c5fb722012-02-28 11:50:359898 // be issuing -- the final header line contains the credentials.
9899 const char* const kAuthCredentials[] = {
9900 "proxy-authorization", "Basic Zm9vOmJhcg==",
9901 };
Ryan Hamilton0239aac2018-05-19 00:03:139902 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
Matt Menke6e879bd2019-03-18 17:26:049903 kAuthCredentials, base::size(kAuthCredentials) / 2, 3,
9904 HttpProxyConnectJob::kH2QuicTunnelPriority,
bncce36dca22015-04-21 22:11:239905 HostPortPair("www.example.org", 443)));
9906 // fetch https://www.example.org/ via HTTP
9907 const char get[] =
9908 "GET / HTTP/1.1\r\n"
9909 "Host: www.example.org\r\n"
9910 "Connection: keep-alive\r\n\r\n";
Ryan Hamilton0239aac2018-05-19 00:03:139911 spdy::SpdySerializedFrame wrapped_get(
Bence Békyd74f4382018-02-20 18:26:199912 spdy_util_.ConstructSpdyDataFrame(3, get, false));
[email protected]0c5fb722012-02-28 11:50:359913
9914 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:419915 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
9916 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:359917 };
9918
9919 // The proxy responds to the connect with a 407, using a persistent
9920 // connection.
thestig9d3bb0c2015-01-24 00:49:519921 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:359922 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:359923 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
9924 };
Ryan Hamilton0239aac2018-05-19 00:03:139925 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
Avi Drissman4365a4782018-12-28 19:26:249926 kAuthStatus, kAuthChallenge, base::size(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:359927
Ryan Hamilton0239aac2018-05-19 00:03:139928 spdy::SpdySerializedFrame conn_resp(
Raul Tambre94493c652019-03-11 17:18:359929 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
[email protected]0c5fb722012-02-28 11:50:359930 const char resp[] = "HTTP/1.1 200 OK\r\n"
9931 "Content-Length: 5\r\n\r\n";
9932
Ryan Hamilton0239aac2018-05-19 00:03:139933 spdy::SpdySerializedFrame wrapped_get_resp(
Bence Békyd74f4382018-02-20 18:26:199934 spdy_util_.ConstructSpdyDataFrame(3, resp, false));
Ryan Hamilton0239aac2018-05-19 00:03:139935 spdy::SpdySerializedFrame wrapped_body(
Bence Békyd74f4382018-02-20 18:26:199936 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
[email protected]0c5fb722012-02-28 11:50:359937 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:419938 CreateMockRead(conn_auth_resp, 1, ASYNC),
9939 CreateMockRead(conn_resp, 4, ASYNC),
9940 CreateMockRead(wrapped_get_resp, 6, ASYNC),
9941 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:139942 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:359943 };
9944
Ryan Sleevib8d7ea02018-05-07 20:01:019945 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:079946 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:359947 // Negotiate SPDY to the proxy
9948 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:369949 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:079950 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:359951 // Vanilla SSL to the server
9952 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:079953 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:359954
9955 TestCompletionCallback callback1;
9956
bnc87dcefc2017-05-25 12:47:589957 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:199958 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]0c5fb722012-02-28 11:50:359959
9960 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:019961 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359962
9963 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019964 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:549965 auto entries = log.GetEntries();
[email protected]0c5fb722012-02-28 11:50:359966 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:009967 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9968 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359969 ExpectLogContainsSomewhere(
9970 entries, pos,
mikecirone8b85c432016-09-08 19:11:009971 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9972 NetLogEventPhase::NONE);
[email protected]0c5fb722012-02-28 11:50:359973
9974 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529975 ASSERT_TRUE(response);
9976 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:359977 EXPECT_EQ(407, response->headers->response_code());
9978 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
Emily Starkf2c9bbd2019-04-09 17:08:589979 EXPECT_TRUE(response->auth_challenge.has_value());
9980 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
[email protected]0c5fb722012-02-28 11:50:359981
9982 TestCompletionCallback callback2;
9983
9984 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
9985 callback2.callback());
robpercival214763f2016-07-01 23:27:019986 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:359987
9988 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019989 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:359990
9991 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529992 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:359993
9994 EXPECT_TRUE(response->headers->IsKeepAlive());
9995 EXPECT_EQ(200, response->headers->response_code());
9996 EXPECT_EQ(5, response->headers->GetContentLength());
9997 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9998
9999 // The password prompt info should not be set.
Emily Starkf2c9bbd2019-04-09 17:08:5810000 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0c5fb722012-02-28 11:50:3510001
[email protected]029c83b62013-01-24 05:28:2010002 LoadTimingInfo load_timing_info;
10003 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10004 TestLoadTimingNotReusedWithPac(load_timing_info,
10005 CONNECT_TIMING_HAS_SSL_TIMES);
10006
[email protected]0c5fb722012-02-28 11:50:3510007 trans.reset();
10008 session->CloseAllConnections();
10009}
10010
[email protected]7c6f7ba2012-04-03 04:09:2910011// Test that an explicitly trusted SPDY proxy can push a resource from an
10012// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:0110013TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:1510014 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910015 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510016 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10017 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:2910018 HttpRequestInfo request;
10019 HttpRequestInfo push_request;
Ramin Halavatib5e433e62018-02-07 07:41:1010020 request.traffic_annotation =
10021 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910022
[email protected]7c6f7ba2012-04-03 04:09:2910023 request.method = "GET";
bncce36dca22015-04-21 22:11:2310024 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:2910025 push_request.method = "GET";
10026 push_request.url = GURL("http://www.another-origin.com/foo.dat");
Ramin Halavatib5e433e62018-02-07 07:41:1010027 push_request.traffic_annotation =
10028 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]7c6f7ba2012-04-03 04:09:2910029
tbansal28e68f82016-02-04 02:56:1510030 // Configure against https proxy server "myproxy:443".
Lily Houghton8c2f97d2018-01-22 05:06:5910031 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910032 ProxyResolutionService::CreateFixedFromPacResult(
10033 "HTTPS myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110034 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710035 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010036
Eric Roman3d8546a2018-09-10 17:00:5210037 session_deps_.proxy_resolution_service->SetProxyDelegate(
10038 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010039
danakj1fd259a02016-04-16 03:17:0910040 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:2910041
Ryan Hamilton0239aac2018-05-19 00:03:1310042 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510043 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310044 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510045 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
[email protected]7c6f7ba2012-04-03 04:09:2910046
10047 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110048 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510049 CreateMockWrite(stream2_priority, 3, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:2910050 };
10051
Ryan Hamilton0239aac2018-05-19 00:03:1310052 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510053 nullptr, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
Bence Béky7bf94362018-01-10 13:19:3610054
Ryan Hamilton0239aac2018-05-19 00:03:1310055 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510056 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:2910057
Ryan Hamilton0239aac2018-05-19 00:03:1310058 spdy::SpdySerializedFrame stream1_body(
10059 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:2910060
Ryan Hamilton0239aac2018-05-19 00:03:1310061 spdy::SpdySerializedFrame stream2_body(
Bence Békyd74f4382018-02-20 18:26:1910062 spdy_util_.ConstructSpdyDataFrame(2, "pushed", true));
[email protected]7c6f7ba2012-04-03 04:09:2910063
10064 MockRead spdy_reads[] = {
Bence Béky7bf94362018-01-10 13:19:3610065 CreateMockRead(stream2_syn, 1, ASYNC),
10066 CreateMockRead(stream1_reply, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510067 CreateMockRead(stream1_body, 4, ASYNC),
10068 CreateMockRead(stream2_body, 5, ASYNC),
10069 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:2910070 };
10071
Ryan Sleevib8d7ea02018-05-07 20:01:0110072 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710073 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:2910074 // Negotiate SPDY to the proxy
10075 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610076 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710077 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:2910078
bnc87dcefc2017-05-25 12:47:5810079 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910080 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]7c6f7ba2012-04-03 04:09:2910081 TestCompletionCallback callback;
10082 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110083 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910084
10085 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110086 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910087 const HttpResponseInfo* response = trans->GetResponseInfo();
10088
bnc87dcefc2017-05-25 12:47:5810089 auto push_trans =
Jeremy Roman0579ed62017-08-29 15:56:1910090 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]90499482013-06-01 00:39:5010091 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110092 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:2910093
10094 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110095 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910096 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
10097
wezca1070932016-05-26 20:30:5210098 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:2910099 EXPECT_TRUE(response->headers->IsKeepAlive());
10100
10101 EXPECT_EQ(200, response->headers->response_code());
10102 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10103
10104 std::string response_data;
10105 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110106 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910107 EXPECT_EQ("hello!", response_data);
10108
[email protected]029c83b62013-01-24 05:28:2010109 LoadTimingInfo load_timing_info;
10110 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10111 TestLoadTimingNotReusedWithPac(load_timing_info,
10112 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10113
[email protected]7c6f7ba2012-04-03 04:09:2910114 // Verify the pushed stream.
wezca1070932016-05-26 20:30:5210115 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:2910116 EXPECT_EQ(200, push_response->headers->response_code());
10117
10118 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110119 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:2910120 EXPECT_EQ("pushed", response_data);
10121
[email protected]029c83b62013-01-24 05:28:2010122 LoadTimingInfo push_load_timing_info;
10123 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
10124 TestLoadTimingReusedWithPac(push_load_timing_info);
10125 // The transactions should share a socket ID, despite being for different
10126 // origins.
10127 EXPECT_EQ(load_timing_info.socket_log_id,
10128 push_load_timing_info.socket_log_id);
10129
[email protected]7c6f7ba2012-04-03 04:09:2910130 trans.reset();
10131 push_trans.reset();
10132 session->CloseAllConnections();
10133}
10134
[email protected]8c843192012-04-05 07:15:0010135// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:0110136TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510137 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910138 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510139 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
10140 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:0010141 HttpRequestInfo request;
10142
10143 request.method = "GET";
bncce36dca22015-04-21 22:11:2310144 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010145 request.traffic_annotation =
10146 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c843192012-04-05 07:15:0010147
Ramin Halavatica8d5252018-03-12 05:33:4910148 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10149 "https://myproxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110150 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0710151 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:5010152
10153 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210154 session_deps_.proxy_resolution_service->SetProxyDelegate(
10155 proxy_delegate.get());
[email protected]61b4efc2012-04-27 18:12:5010156
danakj1fd259a02016-04-16 03:17:0910157 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:0010158
Ryan Hamilton0239aac2018-05-19 00:03:1310159 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510160 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:0010161
Ryan Hamilton0239aac2018-05-19 00:03:1310162 spdy::SpdySerializedFrame push_rst(
10163 spdy_util_.ConstructSpdyRstStream(2, spdy::ERROR_CODE_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:0010164
10165 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110166 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:0010167 };
10168
Ryan Hamilton0239aac2018-05-19 00:03:1310169 spdy::SpdySerializedFrame stream1_reply(
Raul Tambre94493c652019-03-11 17:18:3510170 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
[email protected]8c843192012-04-05 07:15:0010171
Ryan Hamilton0239aac2018-05-19 00:03:1310172 spdy::SpdySerializedFrame stream1_body(
10173 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:0010174
Ryan Hamilton0239aac2018-05-19 00:03:1310175 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Raul Tambre94493c652019-03-11 17:18:3510176 nullptr, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:0010177
10178 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110179 CreateMockRead(stream1_reply, 1, ASYNC),
10180 CreateMockRead(stream2_syn, 2, ASYNC),
10181 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:5910182 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:0010183 };
10184
Ryan Sleevib8d7ea02018-05-07 20:01:0110185 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0710186 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:0010187 // Negotiate SPDY to the proxy
10188 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610189 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0710190 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:0010191
bnc87dcefc2017-05-25 12:47:5810192 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910193 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]8c843192012-04-05 07:15:0010194 TestCompletionCallback callback;
10195 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110196 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:0010197
10198 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110199 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010200 const HttpResponseInfo* response = trans->GetResponseInfo();
10201
wezca1070932016-05-26 20:30:5210202 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:0010203 EXPECT_TRUE(response->headers->IsKeepAlive());
10204
10205 EXPECT_EQ(200, response->headers->response_code());
10206 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10207
10208 std::string response_data;
10209 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110210 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:0010211 EXPECT_EQ("hello!", response_data);
10212
10213 trans.reset();
10214 session->CloseAllConnections();
10215}
10216
tbansal8ef1d3e2016-02-03 04:05:4210217// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
10218// resources.
bncd16676a2016-07-20 16:23:0110219TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:1510220 // Configure the proxy delegate to allow cross-origin SPDY pushes.
Jeremy Roman0579ed62017-08-29 15:56:1910221 auto proxy_delegate = std::make_unique<TestProxyDelegate>();
tbansal28e68f82016-02-04 02:56:1510222 proxy_delegate->set_trusted_spdy_proxy(
10223 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
10224
tbansal8ef1d3e2016-02-03 04:05:4210225 HttpRequestInfo request;
10226
10227 request.method = "GET";
10228 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010229 request.traffic_annotation =
10230 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210231
10232 // Configure against https proxy server "myproxy:70".
Ramin Halavatica8d5252018-03-12 05:33:4910233 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10234 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
tbansal8ef1d3e2016-02-03 04:05:4210235 BoundTestNetLog log;
10236 session_deps_.net_log = log.bound().net_log();
10237
10238 // Enable cross-origin push.
Eric Roman3d8546a2018-09-10 17:00:5210239 session_deps_.proxy_resolution_service->SetProxyDelegate(
10240 proxy_delegate.get());
tbansal8ef1d3e2016-02-03 04:05:4210241
danakj1fd259a02016-04-16 03:17:0910242 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:4210243
Ryan Hamilton0239aac2018-05-19 00:03:1310244 spdy::SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:4510245 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1310246 spdy::SpdySerializedFrame stream2_priority(
tombergan5d22c182017-01-11 02:05:3510247 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
tbansal8ef1d3e2016-02-03 04:05:4210248
10249 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110250 CreateMockWrite(stream1_syn, 0, ASYNC),
tombergan5d22c182017-01-11 02:05:3510251 CreateMockWrite(stream2_priority, 3, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:4210252 };
10253
Ryan Hamilton0239aac2018-05-19 00:03:1310254 spdy::SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:1510255 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210256
Ryan Hamilton0239aac2018-05-19 00:03:1310257 spdy::SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
Bence Béky096cf052017-08-08 23:55:3310258 nullptr, 0, 2, 1, "http://www.example.org/foo.dat"));
bnc38dcd392016-02-09 23:19:4910259
Ryan Hamilton0239aac2018-05-19 00:03:1310260 spdy::SpdySerializedFrame stream1_body(
10261 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210262
Ryan Hamilton0239aac2018-05-19 00:03:1310263 spdy::SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:1510264 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:4210265
Ryan Hamilton0239aac2018-05-19 00:03:1310266 spdy::SpdySerializedFrame stream2_body(
10267 spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:4210268
10269 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110270 CreateMockRead(stream1_reply, 1, ASYNC),
10271 CreateMockRead(stream2_syn, 2, ASYNC),
tombergan5d22c182017-01-11 02:05:3510272 CreateMockRead(stream1_body, 4, ASYNC),
10273 CreateMockRead(stream2_body, 5, ASYNC),
10274 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a hang
tbansal8ef1d3e2016-02-03 04:05:4210275 };
10276
Ryan Sleevib8d7ea02018-05-07 20:01:0110277 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
tbansal8ef1d3e2016-02-03 04:05:4210278 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10279 // Negotiate SPDY to the proxy
10280 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610281 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:4210282 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
10283
bnc87dcefc2017-05-25 12:47:5810284 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1910285 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tbansal8ef1d3e2016-02-03 04:05:4210286 TestCompletionCallback callback;
10287 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0110288 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:4210289
10290 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110291 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210292 const HttpResponseInfo* response = trans->GetResponseInfo();
10293
wezca1070932016-05-26 20:30:5210294 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:4210295 EXPECT_TRUE(response->headers->IsKeepAlive());
10296
10297 EXPECT_EQ(200, response->headers->response_code());
10298 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10299
10300 std::string response_data;
10301 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0110302 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:4210303 EXPECT_EQ("hello!", response_data);
10304
10305 trans.reset();
10306 session->CloseAllConnections();
10307}
10308
[email protected]2df19bb2010-08-25 20:13:4610309// Test HTTPS connections to a site with a bad certificate, going through an
10310// HTTPS proxy
bncd16676a2016-07-20 16:23:0110311TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
Ramin Halavatica8d5252018-03-12 05:33:4910312 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10313 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610314
10315 HttpRequestInfo request;
10316 request.method = "GET";
bncce36dca22015-04-21 22:11:2310317 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010318 request.traffic_annotation =
10319 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2df19bb2010-08-25 20:13:4610320
10321 // Attempt to fetch the URL from a server with a bad cert
10322 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710323 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10324 "Host: www.example.org:443\r\n"
10325 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610326 };
10327
10328 MockRead bad_cert_reads[] = {
10329 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610330 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:4610331 };
10332
10333 // Attempt to fetch the URL with a good cert
10334 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1710335 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10336 "Host: www.example.org:443\r\n"
10337 "Proxy-Connection: keep-alive\r\n\r\n"),
10338 MockWrite("GET / HTTP/1.1\r\n"
10339 "Host: www.example.org\r\n"
10340 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:4610341 };
10342
10343 MockRead good_cert_reads[] = {
10344 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
10345 MockRead("HTTP/1.0 200 OK\r\n"),
10346 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10347 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610348 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:4610349 };
10350
Ryan Sleevib8d7ea02018-05-07 20:01:0110351 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
10352 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
[email protected]8ddf8322012-02-23 18:08:0610353 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
10354 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:4610355
10356 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:0710357 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10358 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
10359 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:4610360
10361 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:0710362 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10363 session_deps_.socket_factory->AddSocketDataProvider(&data);
10364 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:4610365
[email protected]49639fa2011-12-20 23:22:4110366 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:4610367
danakj1fd259a02016-04-16 03:17:0910368 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610369 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]2df19bb2010-08-25 20:13:4610370
tfarina42834112016-09-22 13:38:2010371 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110372 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610373
10374 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110375 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:4610376
bnc691fda62016-08-12 00:43:1610377 rv = trans.RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:0110378 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:4610379
10380 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110381 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:4610382
bnc691fda62016-08-12 00:43:1610383 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]2df19bb2010-08-25 20:13:4610384
wezca1070932016-05-26 20:30:5210385 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:4610386 EXPECT_EQ(100, response->headers->GetContentLength());
10387}
10388
bncd16676a2016-07-20 16:23:0110389TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:4210390 HttpRequestInfo request;
10391 request.method = "GET";
bncce36dca22015-04-21 22:11:2310392 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310393 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10394 "Chromium Ultra Awesome X Edition");
Ramin Halavatib5e433e62018-02-07 07:41:1010395 request.traffic_annotation =
10396 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210397
danakj1fd259a02016-04-16 03:17:0910398 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610399 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710400
[email protected]1c773ea12009-04-28 19:58:4210401 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310402 MockWrite(
10403 "GET / HTTP/1.1\r\n"
10404 "Host: www.example.org\r\n"
10405 "Connection: keep-alive\r\n"
10406 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210407 };
10408
10409 // Lastly, the server responds with the actual content.
10410 MockRead data_reads[] = {
10411 MockRead("HTTP/1.0 200 OK\r\n"),
10412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10413 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610414 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210415 };
10416
Ryan Sleevib8d7ea02018-05-07 20:01:0110417 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710418 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210419
[email protected]49639fa2011-12-20 23:22:4110420 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210421
tfarina42834112016-09-22 13:38:2010422 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110423 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210424
10425 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110426 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210427}
10428
bncd16676a2016-07-20 16:23:0110429TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
Matt Menked732ea42019-03-08 12:05:0010430 // Test user agent values, used both for the request header of the original
10431 // request, and the value returned by the HttpUserAgentSettings. nullptr means
10432 // no request header / no HttpUserAgentSettings object.
10433 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
[email protected]da81f132010-08-18 23:39:2910434
Matt Menked732ea42019-03-08 12:05:0010435 for (const char* setting_user_agent : kTestUserAgents) {
10436 if (!setting_user_agent) {
10437 session_deps_.http_user_agent_settings.reset();
10438 } else {
10439 session_deps_.http_user_agent_settings =
10440 std::make_unique<StaticHttpUserAgentSettings>(
10441 std::string() /* accept-language */, setting_user_agent);
10442 }
10443 session_deps_.proxy_resolution_service =
10444 ProxyResolutionService::CreateFixed("myproxy:70",
10445 TRAFFIC_ANNOTATION_FOR_TESTS);
10446 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10447 for (const char* request_user_agent : kTestUserAgents) {
10448 HttpRequestInfo request;
10449 request.method = "GET";
10450 request.url = GURL("https://www.example.org/");
10451 if (request_user_agent) {
10452 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
10453 request_user_agent);
10454 }
10455 request.traffic_annotation =
10456 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710457
Matt Menked732ea42019-03-08 12:05:0010458 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]da81f132010-08-18 23:39:2910459
Matt Menked732ea42019-03-08 12:05:0010460 std::string expected_request;
10461 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
10462 expected_request =
10463 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10464 "Host: www.example.org:443\r\n"
10465 "Proxy-Connection: keep-alive\r\n\r\n";
10466 } else {
10467 expected_request = base::StringPrintf(
10468 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10469 "Host: www.example.org:443\r\n"
10470 "Proxy-Connection: keep-alive\r\n"
10471 "User-Agent: %s\r\n\r\n",
10472 setting_user_agent);
10473 }
10474 MockWrite data_writes[] = {
10475 MockWrite(expected_request.c_str()),
10476 };
10477 MockRead data_reads[] = {
10478 // Return an error, so the transaction stops here (this test isn't
10479 // interested in the rest).
10480 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10481 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10482 MockRead("Proxy-Connection: close\r\n\r\n"),
10483 };
[email protected]da81f132010-08-18 23:39:2910484
Matt Menked732ea42019-03-08 12:05:0010485 StaticSocketDataProvider data(data_reads, data_writes);
10486 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:2910487
Matt Menked732ea42019-03-08 12:05:0010488 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:2910489
Matt Menked732ea42019-03-08 12:05:0010490 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10491 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10492
10493 rv = callback.WaitForResult();
10494 EXPECT_THAT(rv, IsOk());
10495 }
10496 }
[email protected]da81f132010-08-18 23:39:2910497}
10498
bncd16676a2016-07-20 16:23:0110499TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:4210500 HttpRequestInfo request;
10501 request.method = "GET";
bncce36dca22015-04-21 22:11:2310502 request.url = GURL("http://www.example.org/");
[email protected]c10450102011-06-27 09:06:1610503 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
10504 "http://the.previous.site.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1010505 request.traffic_annotation =
10506 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210507
danakj1fd259a02016-04-16 03:17:0910508 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610509 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710510
[email protected]1c773ea12009-04-28 19:58:4210511 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310512 MockWrite(
10513 "GET / HTTP/1.1\r\n"
10514 "Host: www.example.org\r\n"
10515 "Connection: keep-alive\r\n"
10516 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210517 };
10518
10519 // Lastly, the server responds with the actual content.
10520 MockRead data_reads[] = {
10521 MockRead("HTTP/1.0 200 OK\r\n"),
10522 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10523 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610524 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210525 };
10526
Ryan Sleevib8d7ea02018-05-07 20:01:0110527 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710528 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210529
[email protected]49639fa2011-12-20 23:22:4110530 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210531
tfarina42834112016-09-22 13:38:2010532 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110533 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210534
10535 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110536 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210537}
10538
bncd16676a2016-07-20 16:23:0110539TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210540 HttpRequestInfo request;
10541 request.method = "POST";
bncce36dca22015-04-21 22:11:2310542 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010543 request.traffic_annotation =
10544 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210545
danakj1fd259a02016-04-16 03:17:0910546 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610547 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710548
[email protected]1c773ea12009-04-28 19:58:4210549 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310550 MockWrite(
10551 "POST / HTTP/1.1\r\n"
10552 "Host: www.example.org\r\n"
10553 "Connection: keep-alive\r\n"
10554 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210555 };
10556
10557 // Lastly, the server responds with the actual content.
10558 MockRead data_reads[] = {
10559 MockRead("HTTP/1.0 200 OK\r\n"),
10560 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10561 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610562 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210563 };
10564
Ryan Sleevib8d7ea02018-05-07 20:01:0110565 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710566 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210567
[email protected]49639fa2011-12-20 23:22:4110568 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210569
tfarina42834112016-09-22 13:38:2010570 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110571 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210572
10573 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110574 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210575}
10576
bncd16676a2016-07-20 16:23:0110577TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210578 HttpRequestInfo request;
10579 request.method = "PUT";
bncce36dca22015-04-21 22:11:2310580 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010581 request.traffic_annotation =
10582 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210583
danakj1fd259a02016-04-16 03:17:0910584 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610585 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710586
[email protected]1c773ea12009-04-28 19:58:4210587 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310588 MockWrite(
10589 "PUT / HTTP/1.1\r\n"
10590 "Host: www.example.org\r\n"
10591 "Connection: keep-alive\r\n"
10592 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210593 };
10594
10595 // Lastly, the server responds with the actual content.
10596 MockRead data_reads[] = {
10597 MockRead("HTTP/1.0 200 OK\r\n"),
10598 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10599 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610600 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210601 };
10602
Ryan Sleevib8d7ea02018-05-07 20:01:0110603 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710604 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210605
[email protected]49639fa2011-12-20 23:22:4110606 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210607
tfarina42834112016-09-22 13:38:2010608 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110609 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210610
10611 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110612 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210613}
10614
bncd16676a2016-07-20 16:23:0110615TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:4210616 HttpRequestInfo request;
10617 request.method = "HEAD";
bncce36dca22015-04-21 22:11:2310618 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010619 request.traffic_annotation =
10620 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210621
danakj1fd259a02016-04-16 03:17:0910622 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610623 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710624
[email protected]1c773ea12009-04-28 19:58:4210625 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:1310626 MockWrite("HEAD / HTTP/1.1\r\n"
10627 "Host: www.example.org\r\n"
10628 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210629 };
10630
10631 // Lastly, the server responds with the actual content.
10632 MockRead data_reads[] = {
10633 MockRead("HTTP/1.0 200 OK\r\n"),
10634 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10635 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610636 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210637 };
10638
Ryan Sleevib8d7ea02018-05-07 20:01:0110639 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710640 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210641
[email protected]49639fa2011-12-20 23:22:4110642 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210643
tfarina42834112016-09-22 13:38:2010644 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110645 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210646
10647 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110648 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210649}
10650
bncd16676a2016-07-20 16:23:0110651TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:4210652 HttpRequestInfo request;
10653 request.method = "GET";
bncce36dca22015-04-21 22:11:2310654 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210655 request.load_flags = LOAD_BYPASS_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010656 request.traffic_annotation =
10657 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210658
danakj1fd259a02016-04-16 03:17:0910659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610660 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710661
[email protected]1c773ea12009-04-28 19:58:4210662 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310663 MockWrite(
10664 "GET / HTTP/1.1\r\n"
10665 "Host: www.example.org\r\n"
10666 "Connection: keep-alive\r\n"
10667 "Pragma: no-cache\r\n"
10668 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210669 };
10670
10671 // Lastly, the server responds with the actual content.
10672 MockRead data_reads[] = {
10673 MockRead("HTTP/1.0 200 OK\r\n"),
10674 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10675 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610676 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210677 };
10678
Ryan Sleevib8d7ea02018-05-07 20:01:0110679 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710680 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210681
[email protected]49639fa2011-12-20 23:22:4110682 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210683
tfarina42834112016-09-22 13:38:2010684 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110685 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210686
10687 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110688 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210689}
10690
bncd16676a2016-07-20 16:23:0110691TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:4210692 HttpRequestInfo request;
10693 request.method = "GET";
bncce36dca22015-04-21 22:11:2310694 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:4210695 request.load_flags = LOAD_VALIDATE_CACHE;
Ramin Halavatib5e433e62018-02-07 07:41:1010696 request.traffic_annotation =
10697 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210698
danakj1fd259a02016-04-16 03:17:0910699 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610700 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710701
[email protected]1c773ea12009-04-28 19:58:4210702 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310703 MockWrite(
10704 "GET / HTTP/1.1\r\n"
10705 "Host: www.example.org\r\n"
10706 "Connection: keep-alive\r\n"
10707 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210708 };
10709
10710 // Lastly, the server responds with the actual content.
10711 MockRead data_reads[] = {
10712 MockRead("HTTP/1.0 200 OK\r\n"),
10713 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10714 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610715 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210716 };
10717
Ryan Sleevib8d7ea02018-05-07 20:01:0110718 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710719 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210720
[email protected]49639fa2011-12-20 23:22:4110721 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210722
tfarina42834112016-09-22 13:38:2010723 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110724 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210725
10726 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110727 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210728}
10729
bncd16676a2016-07-20 16:23:0110730TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:4210731 HttpRequestInfo request;
10732 request.method = "GET";
bncce36dca22015-04-21 22:11:2310733 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310734 request.extra_headers.SetHeader("FooHeader", "Bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010735 request.traffic_annotation =
10736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]1c773ea12009-04-28 19:58:4210737
danakj1fd259a02016-04-16 03:17:0910738 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610739 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710740
[email protected]1c773ea12009-04-28 19:58:4210741 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310742 MockWrite(
10743 "GET / HTTP/1.1\r\n"
10744 "Host: www.example.org\r\n"
10745 "Connection: keep-alive\r\n"
10746 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:4210747 };
10748
10749 // Lastly, the server responds with the actual content.
10750 MockRead data_reads[] = {
10751 MockRead("HTTP/1.0 200 OK\r\n"),
10752 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10753 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610754 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:4210755 };
10756
Ryan Sleevib8d7ea02018-05-07 20:01:0110757 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710758 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:4210759
[email protected]49639fa2011-12-20 23:22:4110760 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:4210761
tfarina42834112016-09-22 13:38:2010762 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110763 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:4210764
10765 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110766 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:4210767}
10768
bncd16676a2016-07-20 16:23:0110769TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:4710770 HttpRequestInfo request;
10771 request.method = "GET";
bncce36dca22015-04-21 22:11:2310772 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:4310773 request.extra_headers.SetHeader("referer", "www.foo.com");
10774 request.extra_headers.SetHeader("hEllo", "Kitty");
10775 request.extra_headers.SetHeader("FoO", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1010776 request.traffic_annotation =
10777 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]270c6412010-03-29 22:02:4710778
danakj1fd259a02016-04-16 03:17:0910779 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610780 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2710781
[email protected]270c6412010-03-29 22:02:4710782 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310783 MockWrite(
10784 "GET / HTTP/1.1\r\n"
10785 "Host: www.example.org\r\n"
10786 "Connection: keep-alive\r\n"
10787 "referer: www.foo.com\r\n"
10788 "hEllo: Kitty\r\n"
10789 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:4710790 };
10791
10792 // Lastly, the server responds with the actual content.
10793 MockRead data_reads[] = {
10794 MockRead("HTTP/1.0 200 OK\r\n"),
10795 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10796 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0610797 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:4710798 };
10799
Ryan Sleevib8d7ea02018-05-07 20:01:0110800 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710801 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:4710802
[email protected]49639fa2011-12-20 23:22:4110803 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:4710804
tfarina42834112016-09-22 13:38:2010805 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110806 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:4710807
10808 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110809 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:4710810}
10811
bncd16676a2016-07-20 16:23:0110812TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710813 HttpRequestInfo request;
10814 request.method = "GET";
bncce36dca22015-04-21 22:11:2310815 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010816 request.traffic_annotation =
10817 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710818
Lily Houghton8c2f97d2018-01-22 05:06:5910819 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910820 ProxyResolutionService::CreateFixedFromPacResult(
10821 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110822 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710823 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210824
danakj1fd259a02016-04-16 03:17:0910825 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610826 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210827
[email protected]3cd17242009-06-23 02:59:0210828 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10829 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10830
10831 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410832 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10833 MockWrite("GET / HTTP/1.1\r\n"
10834 "Host: www.example.org\r\n"
10835 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210836
10837 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410838 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10839 MockRead("HTTP/1.0 200 OK\r\n"),
10840 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10841 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0210842
Ryan Sleevib8d7ea02018-05-07 20:01:0110843 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710844 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0210845
[email protected]49639fa2011-12-20 23:22:4110846 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0210847
tfarina42834112016-09-22 13:38:2010848 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110849 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0210850
10851 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110852 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210853
bnc691fda62016-08-12 00:43:1610854 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210855 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:0210856
tbansal2ecbbc72016-10-06 17:15:4710857 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]029c83b62013-01-24 05:28:2010858 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610859 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010860 TestLoadTimingNotReusedWithPac(load_timing_info,
10861 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10862
[email protected]3cd17242009-06-23 02:59:0210863 std::string response_text;
bnc691fda62016-08-12 00:43:1610864 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110865 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0210866 EXPECT_EQ("Payload", response_text);
10867}
10868
bncd16676a2016-07-20 16:23:0110869TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710870 HttpRequestInfo request;
10871 request.method = "GET";
bncce36dca22015-04-21 22:11:2310872 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010873 request.traffic_annotation =
10874 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710875
Lily Houghton8c2f97d2018-01-22 05:06:5910876 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910877 ProxyResolutionService::CreateFixedFromPacResult(
10878 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110879 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710880 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:0210881
danakj1fd259a02016-04-16 03:17:0910882 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610883 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]3cd17242009-06-23 02:59:0210884
[email protected]3cd17242009-06-23 02:59:0210885 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
10886 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10887
10888 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2310889 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
Avi Drissman4365a4782018-12-28 19:26:2410890 base::size(write_buffer)),
10891 MockWrite("GET / HTTP/1.1\r\n"
10892 "Host: www.example.org\r\n"
10893 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:0210894
10895 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410896 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
10897 base::size(read_buffer)),
10898 MockRead("HTTP/1.0 200 OK\r\n"),
10899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10900 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3510901
Ryan Sleevib8d7ea02018-05-07 20:01:0110902 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710903 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3510904
[email protected]8ddf8322012-02-23 18:08:0610905 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710906 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:3510907
[email protected]49639fa2011-12-20 23:22:4110908 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3510909
tfarina42834112016-09-22 13:38:2010910 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110911 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3510912
10913 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110914 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510915
[email protected]029c83b62013-01-24 05:28:2010916 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610917 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010918 TestLoadTimingNotReusedWithPac(load_timing_info,
10919 CONNECT_TIMING_HAS_SSL_TIMES);
10920
bnc691fda62016-08-12 00:43:1610921 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210922 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4710923 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3510924
10925 std::string response_text;
bnc691fda62016-08-12 00:43:1610926 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110927 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3510928 EXPECT_EQ("Payload", response_text);
10929}
10930
bncd16676a2016-07-20 16:23:0110931TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:2010932 HttpRequestInfo request;
10933 request.method = "GET";
bncce36dca22015-04-21 22:11:2310934 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010935 request.traffic_annotation =
10936 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]029c83b62013-01-24 05:28:2010937
Ramin Halavatica8d5252018-03-12 05:33:4910938 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
10939 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110940 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710941 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:2010942
danakj1fd259a02016-04-16 03:17:0910943 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1610944 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]029c83b62013-01-24 05:28:2010945
10946 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
10947 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
10948
10949 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2410950 MockWrite(ASYNC, write_buffer, base::size(write_buffer)),
10951 MockWrite("GET / HTTP/1.1\r\n"
10952 "Host: www.example.org\r\n"
10953 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:2010954
10955 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2410956 MockRead(ASYNC, read_buffer, base::size(read_buffer)),
10957 MockRead("HTTP/1.0 200 OK\r\n"),
10958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
10959 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
[email protected]029c83b62013-01-24 05:28:2010960
Ryan Sleevib8d7ea02018-05-07 20:01:0110961 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0710962 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:2010963
10964 TestCompletionCallback callback;
10965
tfarina42834112016-09-22 13:38:2010966 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0110967 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:2010968
10969 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0110970 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010971
bnc691fda62016-08-12 00:43:1610972 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5210973 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:2010974
10975 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1610976 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2010977 TestLoadTimingNotReused(load_timing_info,
10978 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10979
10980 std::string response_text;
bnc691fda62016-08-12 00:43:1610981 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0110982 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:2010983 EXPECT_EQ("Payload", response_text);
10984}
10985
bncd16676a2016-07-20 16:23:0110986TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2710987 HttpRequestInfo request;
10988 request.method = "GET";
bncce36dca22015-04-21 22:11:2310989 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1010990 request.traffic_annotation =
10991 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2710992
Lily Houghton8c2f97d2018-01-22 05:06:5910993 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4910994 ProxyResolutionService::CreateFixedFromPacResult(
10995 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5110996 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0710997 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3510998
danakj1fd259a02016-04-16 03:17:0910999 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611000 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511001
[email protected]e0c27be2009-07-15 13:09:3511002 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11003 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711004 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311005 0x05, // Version
11006 0x01, // Command (CONNECT)
11007 0x00, // Reserved.
11008 0x03, // Address type (DOMAINNAME).
11009 0x0F, // Length of domain (15)
11010 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11011 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:3711012 };
[email protected]e0c27be2009-07-15 13:09:3511013 const char kSOCKS5OkResponse[] =
11014 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
11015
11016 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411017 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
11018 MockWrite(ASYNC, kSOCKS5OkRequest, base::size(kSOCKS5OkRequest)),
11019 MockWrite("GET / HTTP/1.1\r\n"
11020 "Host: www.example.org\r\n"
11021 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511022
11023 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411024 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11025 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11026 MockRead("HTTP/1.0 200 OK\r\n"),
11027 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11028 MockRead("Payload"),
11029 MockRead(SYNCHRONOUS, OK)};
[email protected]e0c27be2009-07-15 13:09:3511030
Ryan Sleevib8d7ea02018-05-07 20:01:0111031 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711032 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:3511033
[email protected]49639fa2011-12-20 23:22:4111034 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:3511035
tfarina42834112016-09-22 13:38:2011036 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:3511038
11039 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111040 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511041
bnc691fda62016-08-12 00:43:1611042 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211043 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711044 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]e0c27be2009-07-15 13:09:3511045
[email protected]029c83b62013-01-24 05:28:2011046 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611047 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011048 TestLoadTimingNotReusedWithPac(load_timing_info,
11049 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
11050
[email protected]e0c27be2009-07-15 13:09:3511051 std::string response_text;
bnc691fda62016-08-12 00:43:1611052 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111053 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:3511054 EXPECT_EQ("Payload", response_text);
11055}
11056
bncd16676a2016-07-20 16:23:0111057TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:2711058 HttpRequestInfo request;
11059 request.method = "GET";
bncce36dca22015-04-21 22:11:2311060 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011061 request.traffic_annotation =
11062 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711063
Lily Houghton8c2f97d2018-01-22 05:06:5911064 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911065 ProxyResolutionService::CreateFixedFromPacResult(
11066 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5111067 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711068 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:3511069
danakj1fd259a02016-04-16 03:17:0911070 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611071 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]e0c27be2009-07-15 13:09:3511072
[email protected]e0c27be2009-07-15 13:09:3511073 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
11074 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:3711075 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:2311076 0x05, // Version
11077 0x01, // Command (CONNECT)
11078 0x00, // Reserved.
11079 0x03, // Address type (DOMAINNAME).
11080 0x0F, // Length of domain (15)
11081 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
11082 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:3711083 };
11084
[email protected]e0c27be2009-07-15 13:09:3511085 const char kSOCKS5OkResponse[] =
11086 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
11087
11088 MockWrite data_writes[] = {
Avi Drissman4365a4782018-12-28 19:26:2411089 MockWrite(ASYNC, kSOCKS5GreetRequest, base::size(kSOCKS5GreetRequest)),
bncce36dca22015-04-21 22:11:2311090 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
Avi Drissman4365a4782018-12-28 19:26:2411091 base::size(kSOCKS5OkRequest)),
11092 MockWrite("GET / HTTP/1.1\r\n"
11093 "Host: www.example.org\r\n"
11094 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:3511095
11096 MockRead data_reads[] = {
Avi Drissman4365a4782018-12-28 19:26:2411097 MockRead(ASYNC, kSOCKS5GreetResponse, base::size(kSOCKS5GreetResponse)),
11098 MockRead(ASYNC, kSOCKS5OkResponse, base::size(kSOCKS5OkResponse)),
11099 MockRead("HTTP/1.0 200 OK\r\n"),
11100 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
11101 MockRead("Payload"),
11102 MockRead(SYNCHRONOUS, OK)};
[email protected]3cd17242009-06-23 02:59:0211103
Ryan Sleevib8d7ea02018-05-07 20:01:0111104 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0711105 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:0211106
[email protected]8ddf8322012-02-23 18:08:0611107 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0711108 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:0211109
[email protected]49639fa2011-12-20 23:22:4111110 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:0211111
tfarina42834112016-09-22 13:38:2011112 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111113 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:0211114
11115 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111116 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211117
bnc691fda62016-08-12 00:43:1611118 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211119 ASSERT_TRUE(response);
tbansal2ecbbc72016-10-06 17:15:4711120 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, response->proxy_server.scheme());
[email protected]3cd17242009-06-23 02:59:0211121
[email protected]029c83b62013-01-24 05:28:2011122 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1611123 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2011124 TestLoadTimingNotReusedWithPac(load_timing_info,
11125 CONNECT_TIMING_HAS_SSL_TIMES);
11126
[email protected]3cd17242009-06-23 02:59:0211127 std::string response_text;
bnc691fda62016-08-12 00:43:1611128 rv = ReadTransaction(&trans, &response_text);
robpercival214763f2016-07-01 23:27:0111129 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:0211130 EXPECT_EQ("Payload", response_text);
11131}
11132
[email protected]448d4ca52012-03-04 04:12:2311133namespace {
11134
Matt Menkef6edce752019-03-19 17:21:5611135// Tests that for connection endpoints the group ids are correctly set.
[email protected]2d731a32010-04-29 01:04:0611136
Matt Menkef6edce752019-03-19 17:21:5611137struct GroupIdTest {
[email protected]2d731a32010-04-29 01:04:0611138 std::string proxy_server;
11139 std::string url;
Matt Menkef6edce752019-03-19 17:21:5611140 ClientSocketPool::GroupId expected_group_id;
[email protected]e60e47a2010-07-14 03:37:1811141 bool ssl;
[email protected]2d731a32010-04-29 01:04:0611142};
11143
Matt Menkef6edce752019-03-19 17:21:5611144std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
[email protected]bb88e1d32013-05-03 23:11:0711145 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:0911146 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:0611147
bnc525e175a2016-06-20 12:36:4011148 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5311149 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2111150 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnc7dc7e1b42015-07-28 14:43:1211151 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2111152 http_server_properties->SetHttp2AlternativeService(
bncaa60ff402016-06-22 19:12:4211153 url::SchemeHostPort("https", "host.with.alternate", 443),
zhongyi3d4a55e72016-04-22 20:36:4611154 alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:0611155
11156 return session;
11157}
11158
Matt Menkef6edce752019-03-19 17:21:5611159int GroupIdTransactionHelper(const std::string& url,
11160 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:0611161 HttpRequestInfo request;
11162 request.method = "GET";
11163 request.url = GURL(url);
Ramin Halavatib5e433e62018-02-07 07:41:1011164 request.traffic_annotation =
11165 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d731a32010-04-29 01:04:0611166
bnc691fda62016-08-12 00:43:1611167 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
[email protected]cb9bf6ca2011-01-28 13:15:2711168
[email protected]49639fa2011-12-20 23:22:4111169 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:0611170
11171 // We do not complete this request, the dtor will clean the transaction up.
tfarina42834112016-09-22 13:38:2011172 return trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]2d731a32010-04-29 01:04:0611173}
11174
[email protected]448d4ca52012-03-04 04:12:2311175} // namespace
11176
Matt Menkef6edce752019-03-19 17:21:5611177TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
11178 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311179 {
Matt Menkef6edce752019-03-19 17:21:5611180 "", // unused
11181 "http://www.example.org/direct",
11182 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11183 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911184 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611185 false,
bncce36dca22015-04-21 22:11:2311186 },
11187 {
Matt Menkef6edce752019-03-19 17:21:5611188 "", // unused
11189 "http://[2001:1418:13:1::25]/direct",
11190 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
11191 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911192 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611193 false,
bncce36dca22015-04-21 22:11:2311194 },
[email protected]04e5be32009-06-26 20:00:3111195
bncce36dca22015-04-21 22:11:2311196 // SSL Tests
11197 {
Matt Menkef6edce752019-03-19 17:21:5611198 "", // unused
11199 "https://www.example.org/direct_ssl",
11200 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11201 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911202 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611203 true,
bncce36dca22015-04-21 22:11:2311204 },
11205 {
Matt Menkef6edce752019-03-19 17:21:5611206 "", // unused
11207 "https://[2001:1418:13:1::25]/direct",
11208 ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
11209 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911210 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611211 true,
bncce36dca22015-04-21 22:11:2311212 },
11213 {
Matt Menkef6edce752019-03-19 17:21:5611214 "", // unused
11215 "https://host.with.alternate/direct",
11216 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11217 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911218 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menkef6edce752019-03-19 17:21:5611219 true,
bncce36dca22015-04-21 22:11:2311220 },
[email protected]2d731a32010-04-29 01:04:0611221 };
[email protected]2ff8b312010-04-26 22:20:5411222
Avi Drissman4365a4782018-12-28 19:26:2411223 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911224 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911225 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11226 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911227 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611228 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611229
mmenkee65e7af2015-10-13 17:16:4211230 HttpNetworkSessionPeer peer(session.get());
Matt Menkef6edce752019-03-19 17:21:5611231 CaptureGroupIdTransportSocketPool* transport_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611232 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911233 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011234 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
11235 base::WrapUnique(transport_conn_pool));
dchengc7eeda422015-12-26 03:56:4811236 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611237
11238 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611239 GroupIdTransactionHelper(tests[i].url, session.get()));
11240 EXPECT_EQ(tests[i].expected_group_id,
11241 transport_conn_pool->last_group_id_received());
Matt Menke9d5e2c92019-02-05 01:42:2311242 EXPECT_TRUE(transport_conn_pool->socket_requested());
[email protected]2d731a32010-04-29 01:04:0611243 }
[email protected]2d731a32010-04-29 01:04:0611244}
11245
Matt Menkef6edce752019-03-19 17:21:5611246TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
11247 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311248 {
Matt Menke4802de62019-03-08 22:47:5011249 "http_proxy",
11250 "http://www.example.org/http_proxy_normal",
Matt Menkef6edce752019-03-19 17:21:5611251 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11252 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911253 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011254 false,
bncce36dca22015-04-21 22:11:2311255 },
[email protected]2d731a32010-04-29 01:04:0611256
bncce36dca22015-04-21 22:11:2311257 // SSL Tests
11258 {
Matt Menke4802de62019-03-08 22:47:5011259 "http_proxy",
11260 "https://www.example.org/http_connect_ssl",
Matt Menkef6edce752019-03-19 17:21:5611261 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11262 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911263 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011264 true,
bncce36dca22015-04-21 22:11:2311265 },
[email protected]af3490e2010-10-16 21:02:2911266
bncce36dca22015-04-21 22:11:2311267 {
Matt Menke4802de62019-03-08 22:47:5011268 "http_proxy",
11269 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611270 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11271 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911272 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011273 true,
bncce36dca22015-04-21 22:11:2311274 },
[email protected]2d731a32010-04-29 01:04:0611275 };
11276
Avi Drissman4365a4782018-12-28 19:26:2411277 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911278 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911279 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11280 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911281 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611282 SetupSessionForGroupIdTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:0611283
mmenkee65e7af2015-10-13 17:16:4211284 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:0611285
Matt Menkee8648fa2019-01-17 16:47:0711286 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
11287 HostPortPair("http_proxy", 80));
Matt Menkef6edce752019-03-19 17:21:5611288 CaptureGroupIdTransportSocketPool* http_proxy_pool =
Matt Menked6fd2a52019-03-20 06:14:3611289 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911290 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011291 mock_pool_manager->SetSocketPool(proxy_server,
11292 base::WrapUnique(http_proxy_pool));
dchengc7eeda422015-12-26 03:56:4811293 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:0611294
11295 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611296 GroupIdTransactionHelper(tests[i].url, session.get()));
11297 EXPECT_EQ(tests[i].expected_group_id,
11298 http_proxy_pool->last_group_id_received());
[email protected]2d731a32010-04-29 01:04:0611299 }
[email protected]2d731a32010-04-29 01:04:0611300}
11301
Matt Menkef6edce752019-03-19 17:21:5611302TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
11303 const GroupIdTest tests[] = {
bncce36dca22015-04-21 22:11:2311304 {
Matt Menke4802de62019-03-08 22:47:5011305 "socks4://socks_proxy:1080",
11306 "http://www.example.org/socks4_direct",
Matt Menkef6edce752019-03-19 17:21:5611307 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11308 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911309 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011310 false,
bncce36dca22015-04-21 22:11:2311311 },
11312 {
Matt Menke4802de62019-03-08 22:47:5011313 "socks5://socks_proxy:1080",
11314 "http://www.example.org/socks5_direct",
Matt Menkef6edce752019-03-19 17:21:5611315 ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
11316 ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5911317 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011318 false,
bncce36dca22015-04-21 22:11:2311319 },
[email protected]2d731a32010-04-29 01:04:0611320
bncce36dca22015-04-21 22:11:2311321 // SSL Tests
11322 {
Matt Menke4802de62019-03-08 22:47:5011323 "socks4://socks_proxy:1080",
11324 "https://www.example.org/socks4_ssl",
Matt Menkef6edce752019-03-19 17:21:5611325 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11326 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911327 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011328 true,
bncce36dca22015-04-21 22:11:2311329 },
11330 {
Matt Menke4802de62019-03-08 22:47:5011331 "socks5://socks_proxy:1080",
11332 "https://www.example.org/socks5_ssl",
Matt Menkef6edce752019-03-19 17:21:5611333 ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
11334 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911335 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011336 true,
bncce36dca22015-04-21 22:11:2311337 },
[email protected]af3490e2010-10-16 21:02:2911338
bncce36dca22015-04-21 22:11:2311339 {
Matt Menke4802de62019-03-08 22:47:5011340 "socks4://socks_proxy:1080",
11341 "https://host.with.alternate/direct",
Matt Menkef6edce752019-03-19 17:21:5611342 ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
11343 ClientSocketPool::SocketType::kSsl,
Matt Menkebdf777802019-04-22 19:38:5911344 PrivacyMode::PRIVACY_MODE_DISABLED),
Matt Menke4802de62019-03-08 22:47:5011345 true,
bncce36dca22015-04-21 22:11:2311346 },
[email protected]04e5be32009-06-26 20:00:3111347 };
11348
Avi Drissman4365a4782018-12-28 19:26:2411349 for (size_t i = 0; i < base::size(tests); ++i) {
Lily Houghton8c2f97d2018-01-22 05:06:5911350 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4911351 ProxyResolutionService::CreateFixed(tests[i].proxy_server,
11352 TRAFFIC_ANNOTATION_FOR_TESTS);
danakj1fd259a02016-04-16 03:17:0911353 std::unique_ptr<HttpNetworkSession> session(
Matt Menkef6edce752019-03-19 17:21:5611354 SetupSessionForGroupIdTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:0211355
mmenkee65e7af2015-10-13 17:16:4211356 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:3111357
Matt Menkee8648fa2019-01-17 16:47:0711358 ProxyServer proxy_server(
11359 ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
11360 ASSERT_TRUE(proxy_server.is_valid());
Matt Menkef6edce752019-03-19 17:21:5611361 CaptureGroupIdTransportSocketPool* socks_conn_pool =
Matt Menked6fd2a52019-03-20 06:14:3611362 new CaptureGroupIdTransportSocketPool(&dummy_connect_job_params_);
Jeremy Roman0579ed62017-08-29 15:56:1911363 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4011364 mock_pool_manager->SetSocketPool(proxy_server,
11365 base::WrapUnique(socks_conn_pool));
dchengc7eeda422015-12-26 03:56:4811366 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:3111367
bnc691fda62016-08-12 00:43:1611368 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]04e5be32009-06-26 20:00:3111369
[email protected]2d731a32010-04-29 01:04:0611370 EXPECT_EQ(ERR_IO_PENDING,
Matt Menkef6edce752019-03-19 17:21:5611371 GroupIdTransactionHelper(tests[i].url, session.get()));
11372 EXPECT_EQ(tests[i].expected_group_id,
11373 socks_conn_pool->last_group_id_received());
[email protected]04e5be32009-06-26 20:00:3111374 }
11375}
11376
bncd16676a2016-07-20 16:23:0111377TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:2711378 HttpRequestInfo request;
11379 request.method = "GET";
bncce36dca22015-04-21 22:11:2311380 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011381 request.traffic_annotation =
11382 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2711383
Ramin Halavatica8d5252018-03-12 05:33:4911384 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11385 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]b59ff372009-07-15 22:04:3211386
[email protected]69719062010-01-05 20:09:2111387 // This simulates failure resolving all hostnames; that means we will fail
11388 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:0711389 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:3211390
danakj1fd259a02016-04-16 03:17:0911391 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611392 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]9172a982009-06-06 00:30:2511393
[email protected]49639fa2011-12-20 23:22:4111394 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:2511395
tfarina42834112016-09-22 13:38:2011396 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111397 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:2511398
[email protected]9172a982009-06-06 00:30:2511399 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111400 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:2511401}
11402
[email protected]0877e3d2009-10-17 22:29:5711403// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:0111404TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:5711405 HttpRequestInfo request;
11406 request.method = "GET";
11407 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011408 request.traffic_annotation =
11409 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711410
11411 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:0611412 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711413 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111414 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
[email protected]bb88e1d32013-05-03 23:11:0711415 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911416 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711417
[email protected]49639fa2011-12-20 23:22:4111418 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711419
bnc691fda62016-08-12 00:43:1611420 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711421
tfarina42834112016-09-22 13:38:2011422 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111423 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711424
11425 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111426 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:5911427
11428 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611429 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911430 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711431}
11432
zmo9528c9f42015-08-04 22:12:0811433// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:0111434TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:5711435 HttpRequestInfo request;
11436 request.method = "GET";
11437 request.url = GURL("http://www.foo.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1011438 request.traffic_annotation =
11439 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711440
11441 MockRead data_reads[] = {
11442 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:0611443 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711444 };
11445
Ryan Sleevib8d7ea02018-05-07 20:01:0111446 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711447 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:0911448 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711449
[email protected]49639fa2011-12-20 23:22:4111450 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711451
bnc691fda62016-08-12 00:43:1611452 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711453
tfarina42834112016-09-22 13:38:2011454 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111455 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711456
11457 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111458 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811459
bnc691fda62016-08-12 00:43:1611460 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211461 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:0811462
wezca1070932016-05-26 20:30:5211463 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:0811464 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11465
11466 std::string response_data;
bnc691fda62016-08-12 00:43:1611467 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111468 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:0811469 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:5911470
11471 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1611472 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5911473 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:5711474}
11475
11476// Make sure that a dropped connection while draining the body for auth
11477// restart does the right thing.
bncd16676a2016-07-20 16:23:0111478TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:5711479 HttpRequestInfo request;
11480 request.method = "GET";
bncce36dca22015-04-21 22:11:2311481 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011482 request.traffic_annotation =
11483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711484
11485 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311486 MockWrite(
11487 "GET / HTTP/1.1\r\n"
11488 "Host: www.example.org\r\n"
11489 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711490 };
11491
11492 MockRead data_reads1[] = {
11493 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
11494 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11495 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11496 MockRead("Content-Length: 14\r\n\r\n"),
11497 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:0611498 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:5711499 };
11500
Ryan Sleevib8d7ea02018-05-07 20:01:0111501 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0711502 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:5711503
bnc691fda62016-08-12 00:43:1611504 // After calling trans.RestartWithAuth(), this is the request we should
[email protected]0877e3d2009-10-17 22:29:5711505 // be issuing -- the final header line contains the credentials.
11506 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311507 MockWrite(
11508 "GET / HTTP/1.1\r\n"
11509 "Host: www.example.org\r\n"
11510 "Connection: keep-alive\r\n"
11511 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:5711512 };
11513
11514 // Lastly, the server responds with the actual content.
11515 MockRead data_reads2[] = {
11516 MockRead("HTTP/1.1 200 OK\r\n"),
11517 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11518 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611519 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:5711520 };
11521
Ryan Sleevib8d7ea02018-05-07 20:01:0111522 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]bb88e1d32013-05-03 23:11:0711523 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:0911524 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:5711525
[email protected]49639fa2011-12-20 23:22:4111526 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:5711527
bnc691fda62016-08-12 00:43:1611528 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011529
tfarina42834112016-09-22 13:38:2011530 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111531 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711532
11533 rv = callback1.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 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211537 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811538 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
[email protected]0877e3d2009-10-17 22:29:5711539
[email protected]49639fa2011-12-20 23:22:4111540 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:5711541
bnc691fda62016-08-12 00:43:1611542 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:0111543 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711544
11545 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111546 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:5711547
bnc691fda62016-08-12 00:43:1611548 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211549 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811550 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]0877e3d2009-10-17 22:29:5711551 EXPECT_EQ(100, response->headers->GetContentLength());
11552}
11553
11554// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:0111555TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
Ramin Halavatica8d5252018-03-12 05:33:4911556 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
11557 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711558
11559 HttpRequestInfo request;
11560 request.method = "GET";
bncce36dca22015-04-21 22:11:2311561 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011562 request.traffic_annotation =
11563 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]0877e3d2009-10-17 22:29:5711564
11565 MockRead proxy_reads[] = {
11566 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:0611567 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:5711568 };
11569
Ryan Sleevib8d7ea02018-05-07 20:01:0111570 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
[email protected]8ddf8322012-02-23 18:08:0611571 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:5711572
[email protected]bb88e1d32013-05-03 23:11:0711573 session_deps_.socket_factory->AddSocketDataProvider(&data);
11574 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:5711575
[email protected]49639fa2011-12-20 23:22:4111576 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:5711577
[email protected]bb88e1d32013-05-03 23:11:0711578 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:5711579
danakj1fd259a02016-04-16 03:17:0911580 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611581 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0877e3d2009-10-17 22:29:5711582
tfarina42834112016-09-22 13:38:2011583 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111584 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:5711585
11586 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111587 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:5711588}
11589
bncd16676a2016-07-20 16:23:0111590TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:4611591 HttpRequestInfo request;
11592 request.method = "GET";
bncce36dca22015-04-21 22:11:2311593 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011594 request.traffic_annotation =
11595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]9492e4a2010-02-24 00:58:4611596
danakj1fd259a02016-04-16 03:17:0911597 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611598 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2711599
[email protected]e22e1362009-11-23 21:31:1211600 MockRead data_reads[] = {
11601 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0611602 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:1211603 };
[email protected]9492e4a2010-02-24 00:58:4611604
Ryan Sleevib8d7ea02018-05-07 20:01:0111605 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711606 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:4611607
[email protected]49639fa2011-12-20 23:22:4111608 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:4611609
tfarina42834112016-09-22 13:38:2011610 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111611 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:4611612
robpercival214763f2016-07-01 23:27:0111613 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:4611614
bnc691fda62016-08-12 00:43:1611615 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211616 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:4611617
wezca1070932016-05-26 20:30:5211618 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:4611619 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
11620
11621 std::string response_data;
bnc691fda62016-08-12 00:43:1611622 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0111623 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:1211624}
11625
bncd16676a2016-07-20 16:23:0111626TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:1511627 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:5211628 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:1411629 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:2111630 UploadFileElementReader::ScopedOverridingContentLengthForTests
11631 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:3311632
danakj1fd259a02016-04-16 03:17:0911633 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911634 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411635 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
ricea2deef682016-09-09 08:04:0711636 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211637 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711638
11639 HttpRequestInfo request;
11640 request.method = "POST";
bncce36dca22015-04-21 22:11:2311641 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711642 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011643 request.traffic_annotation =
11644 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711645
danakj1fd259a02016-04-16 03:17:0911646 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611647 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]95d88ffe2010-02-04 21:25:3311648
11649 MockRead data_reads[] = {
11650 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11651 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0611652 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:3311653 };
Ryan Sleevib8d7ea02018-05-07 20:01:0111654 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0711655 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:3311656
[email protected]49639fa2011-12-20 23:22:4111657 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:3311658
tfarina42834112016-09-22 13:38:2011659 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111660 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:3311661
11662 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111663 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:3311664
bnc691fda62016-08-12 00:43:1611665 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211666 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:3311667
maksim.sisove869bf52016-06-23 17:11:5211668 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:3311669
[email protected]dd3aa792013-07-16 19:10:2311670 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:3311671}
11672
bncd16676a2016-07-20 16:23:0111673TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:1511674 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:5211675 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:3611676 std::string temp_file_content("Unreadable file.");
lazyboy8df84fc2017-04-12 02:12:4811677 ASSERT_EQ(static_cast<int>(temp_file_content.length()),
11678 base::WriteFile(temp_file, temp_file_content.c_str(),
11679 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:1111680 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:3611681
danakj1fd259a02016-04-16 03:17:0911682 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
Jeremy Roman0579ed62017-08-29 15:56:1911683 element_readers.push_back(std::make_unique<UploadFileElementReader>(
avibf0746c2015-12-09 19:53:1411684 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
ricea2deef682016-09-09 08:04:0711685 std::numeric_limits<uint64_t>::max(), base::Time()));
olli.raula6df48b2a2015-11-26 07:40:2211686 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:2711687
11688 HttpRequestInfo request;
11689 request.method = "POST";
bncce36dca22015-04-21 22:11:2311690 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:2711691 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011692 request.traffic_annotation =
11693 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]329b68b2012-11-14 17:54:2711694
[email protected]999dd8c2013-11-12 06:45:5411695 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:0911696 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611697 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]6624b4622010-03-29 19:58:3611698
Ryan Sleevib8d7ea02018-05-07 20:01:0111699 StaticSocketDataProvider data;
[email protected]bb88e1d32013-05-03 23:11:0711700 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:3611701
[email protected]49639fa2011-12-20 23:22:4111702 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:3611703
tfarina42834112016-09-22 13:38:2011704 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111705 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:3611706
11707 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111708 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:3611709
[email protected]dd3aa792013-07-16 19:10:2311710 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:3611711}
11712
bncd16676a2016-07-20 16:23:0111713TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:0311714 class FakeUploadElementReader : public UploadElementReader {
11715 public:
Chris Watkins7a41d3552017-12-01 02:13:2711716 FakeUploadElementReader() = default;
11717 ~FakeUploadElementReader() override = default;
[email protected]02cad5d2013-10-02 08:14:0311718
Matt Menkecc1d3a902018-02-05 18:27:3311719 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
[email protected]02cad5d2013-10-02 08:14:0311720
11721 // UploadElementReader overrides:
Matt Menkecc1d3a902018-02-05 18:27:3311722 int Init(CompletionOnceCallback callback) override {
11723 callback_ = std::move(callback);
[email protected]02cad5d2013-10-02 08:14:0311724 return ERR_IO_PENDING;
11725 }
avibf0746c2015-12-09 19:53:1411726 uint64_t GetContentLength() const override { return 0; }
11727 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:2011728 int Read(IOBuffer* buf,
11729 int buf_length,
Matt Menkecc1d3a902018-02-05 18:27:3311730 CompletionOnceCallback callback) override {
[email protected]02cad5d2013-10-02 08:14:0311731 return ERR_FAILED;
11732 }
11733
11734 private:
Matt Menkecc1d3a902018-02-05 18:27:3311735 CompletionOnceCallback callback_;
[email protected]02cad5d2013-10-02 08:14:0311736 };
11737
11738 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:0911739 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11740 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:2211741 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:0311742
11743 HttpRequestInfo request;
11744 request.method = "POST";
bncce36dca22015-04-21 22:11:2311745 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:0311746 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1011747 request.traffic_annotation =
11748 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02cad5d2013-10-02 08:14:0311749
danakj1fd259a02016-04-16 03:17:0911750 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5811751 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1911752 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]02cad5d2013-10-02 08:14:0311753
11754 StaticSocketDataProvider data;
11755 session_deps_.socket_factory->AddSocketDataProvider(&data);
11756
11757 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2011758 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111759 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:5511760 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:0311761
11762 // Transaction is pending on request body initialization.
Matt Menkecc1d3a902018-02-05 18:27:3311763 CompletionOnceCallback init_callback = fake_reader->TakeCallback();
11764 ASSERT_FALSE(init_callback.is_null());
[email protected]02cad5d2013-10-02 08:14:0311765
11766 // Return Init()'s result after the transaction gets destroyed.
11767 trans.reset();
Matt Menkecc1d3a902018-02-05 18:27:3311768 std::move(init_callback).Run(OK); // Should not crash.
[email protected]02cad5d2013-10-02 08:14:0311769}
11770
[email protected]aeefc9e82010-02-19 16:18:2711771// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:0111772TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:2711773 HttpRequestInfo request;
11774 request.method = "GET";
bncce36dca22015-04-21 22:11:2311775 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011776 request.traffic_annotation =
11777 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]aeefc9e82010-02-19 16:18:2711778
11779 // First transaction will request a resource and receive a Basic challenge
11780 // with realm="first_realm".
11781 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2311782 MockWrite(
11783 "GET / HTTP/1.1\r\n"
11784 "Host: www.example.org\r\n"
11785 "Connection: keep-alive\r\n"
11786 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711787 };
11788 MockRead data_reads1[] = {
11789 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11790 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11791 "\r\n"),
11792 };
11793
bnc691fda62016-08-12 00:43:1611794 // After calling trans.RestartWithAuth(), provide an Authentication header
[email protected]aeefc9e82010-02-19 16:18:2711795 // for first_realm. The server will reject and provide a challenge with
11796 // second_realm.
11797 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:2311798 MockWrite(
11799 "GET / HTTP/1.1\r\n"
11800 "Host: www.example.org\r\n"
11801 "Connection: keep-alive\r\n"
11802 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
11803 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711804 };
11805 MockRead data_reads2[] = {
11806 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11807 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
11808 "\r\n"),
11809 };
11810
11811 // This again fails, and goes back to first_realm. Make sure that the
11812 // entry is removed from cache.
11813 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:2311814 MockWrite(
11815 "GET / HTTP/1.1\r\n"
11816 "Host: www.example.org\r\n"
11817 "Connection: keep-alive\r\n"
11818 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
11819 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711820 };
11821 MockRead data_reads3[] = {
11822 MockRead("HTTP/1.1 401 Unauthorized\r\n"
11823 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
11824 "\r\n"),
11825 };
11826
11827 // Try one last time (with the correct password) and get the resource.
11828 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:2311829 MockWrite(
11830 "GET / HTTP/1.1\r\n"
11831 "Host: www.example.org\r\n"
11832 "Connection: keep-alive\r\n"
11833 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
11834 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:2711835 };
11836 MockRead data_reads4[] = {
11837 MockRead("HTTP/1.1 200 OK\r\n"
11838 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:5011839 "Content-Length: 5\r\n"
11840 "\r\n"
11841 "hello"),
[email protected]aeefc9e82010-02-19 16:18:2711842 };
11843
Ryan Sleevib8d7ea02018-05-07 20:01:0111844 StaticSocketDataProvider data1(data_reads1, data_writes1);
11845 StaticSocketDataProvider data2(data_reads2, data_writes2);
11846 StaticSocketDataProvider data3(data_reads3, data_writes3);
11847 StaticSocketDataProvider data4(data_reads4, data_writes4);
[email protected]bb88e1d32013-05-03 23:11:0711848 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11849 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11850 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11851 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:2711852
[email protected]49639fa2011-12-20 23:22:4111853 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:2711854
danakj1fd259a02016-04-16 03:17:0911855 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1611856 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5011857
[email protected]aeefc9e82010-02-19 16:18:2711858 // Issue the first request with Authorize headers. There should be a
11859 // password prompt for first_realm waiting to be filled in after the
11860 // transaction completes.
tfarina42834112016-09-22 13:38:2011861 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0111862 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711863 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0111864 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611865 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211866 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811867 base::Optional<AuthChallengeInfo> challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211868 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411869 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311870 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411871 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911872 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711873
11874 // Issue the second request with an incorrect password. There should be a
11875 // password prompt for second_realm waiting to be filled in after the
11876 // transaction completes.
[email protected]49639fa2011-12-20 23:22:4111877 TestCompletionCallback callback2;
bnc691fda62016-08-12 00:43:1611878 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
11879 callback2.callback());
robpercival214763f2016-07-01 23:27:0111880 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711881 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:0111882 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611883 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211884 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811885 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211886 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411887 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311888 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411889 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911890 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711891
11892 // Issue the third request with another incorrect password. There should be
11893 // a password prompt for first_realm waiting to be filled in. If the password
11894 // prompt is not present, it indicates that the HttpAuthCacheEntry for
11895 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:4111896 TestCompletionCallback callback3;
bnc691fda62016-08-12 00:43:1611897 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
11898 callback3.callback());
robpercival214763f2016-07-01 23:27:0111899 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711900 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:0111901 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611902 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211903 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811904 challenge = response->auth_challenge;
wezca1070932016-05-26 20:30:5211905 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:0411906 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:4311907 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:0411908 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:1911909 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:2711910
11911 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:4111912 TestCompletionCallback callback4;
bnc691fda62016-08-12 00:43:1611913 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
11914 callback4.callback());
robpercival214763f2016-07-01 23:27:0111915 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:2711916 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:0111917 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1611918 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5211919 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5811920 EXPECT_FALSE(response->auth_challenge.has_value());
[email protected]aeefc9e82010-02-19 16:18:2711921}
11922
Bence Béky230ac612017-08-30 19:17:0811923// Regression test for https://crbug.com/754395.
11924TEST_F(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
11925 MockRead data_reads[] = {
11926 MockRead("HTTP/1.1 200 OK\r\n"),
11927 MockRead(kAlternativeServiceHttpHeader),
11928 MockRead("\r\n"),
11929 MockRead("hello world"),
11930 MockRead(SYNCHRONOUS, OK),
11931 };
11932
11933 HttpRequestInfo request;
11934 request.method = "GET";
11935 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011936 request.traffic_annotation =
11937 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Béky230ac612017-08-30 19:17:0811938
Ryan Sleevib8d7ea02018-05-07 20:01:0111939 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
Bence Béky230ac612017-08-30 19:17:0811940 session_deps_.socket_factory->AddSocketDataProvider(&data);
11941
11942 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4911943 ssl.ssl_info.cert =
11944 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
11945 ASSERT_TRUE(ssl.ssl_info.cert);
11946 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
Bence Béky230ac612017-08-30 19:17:0811947 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11948
11949 TestCompletionCallback callback;
11950
11951 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11952 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11953
11954 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
11955 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11956
11957 url::SchemeHostPort test_server(request.url);
11958 HttpServerProperties* http_server_properties =
11959 session->http_server_properties();
11960 EXPECT_TRUE(
11961 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
11962
11963 EXPECT_THAT(callback.WaitForResult(), IsOk());
11964
11965 const HttpResponseInfo* response = trans.GetResponseInfo();
11966 ASSERT_TRUE(response);
11967 ASSERT_TRUE(response->headers);
11968 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11969 EXPECT_FALSE(response->was_fetched_via_spdy);
11970 EXPECT_FALSE(response->was_alpn_negotiated);
11971
11972 std::string response_data;
11973 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
11974 EXPECT_EQ("hello world", response_data);
11975
11976 EXPECT_TRUE(
11977 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
11978}
11979
bncd16676a2016-07-20 16:23:0111980TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:5211981 MockRead data_reads[] = {
11982 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4311983 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5211984 MockRead("\r\n"),
11985 MockRead("hello world"),
11986 MockRead(SYNCHRONOUS, OK),
11987 };
11988
11989 HttpRequestInfo request;
11990 request.method = "GET";
bncb26024382016-06-29 02:39:4511991 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1011992 request.traffic_annotation =
11993 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5211994
Ryan Sleevib8d7ea02018-05-07 20:01:0111995 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5211996 session_deps_.socket_factory->AddSocketDataProvider(&data);
11997
bncb26024382016-06-29 02:39:4511998 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4911999 ssl.ssl_info.cert =
12000 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12001 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512002 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12003
bncc958faa2015-07-31 18:14:5212004 TestCompletionCallback callback;
12005
danakj1fd259a02016-04-16 03:17:0912006 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612007 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212008
tfarina42834112016-09-22 13:38:2012009 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112010 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212011
bncb26024382016-06-29 02:39:4512012 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012013 HttpServerProperties* http_server_properties =
12014 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412015 EXPECT_TRUE(
12016 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bncc958faa2015-07-31 18:14:5212017
robpercival214763f2016-07-01 23:27:0112018 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212019
bnc691fda62016-08-12 00:43:1612020 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212021 ASSERT_TRUE(response);
12022 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212023 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12024 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212025 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212026
12027 std::string response_data;
bnc691fda62016-08-12 00:43:1612028 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212029 EXPECT_EQ("hello world", response_data);
12030
zhongyic4de03032017-05-19 04:07:3412031 AlternativeServiceInfoVector alternative_service_info_vector =
12032 http_server_properties->GetAlternativeServiceInfos(test_server);
12033 ASSERT_EQ(1u, alternative_service_info_vector.size());
12034 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
12035 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412036 alternative_service_info_vector[0].alternative_service());
bncc958faa2015-07-31 18:14:5212037}
12038
bnce3dd56f2016-06-01 10:37:1112039// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:0112040TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112041 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:1112042 MockRead data_reads[] = {
12043 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312044 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:1112045 MockRead("\r\n"),
12046 MockRead("hello world"),
12047 MockRead(SYNCHRONOUS, OK),
12048 };
12049
12050 HttpRequestInfo request;
12051 request.method = "GET";
12052 request.url = GURL("http://www.example.org/");
12053 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012054 request.traffic_annotation =
12055 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112056
Ryan Sleevib8d7ea02018-05-07 20:01:0112057 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112058 session_deps_.socket_factory->AddSocketDataProvider(&data);
12059
12060 TestCompletionCallback callback;
12061
12062 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612063 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112064
12065 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:4012066 HttpServerProperties* http_server_properties =
12067 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412068 EXPECT_TRUE(
12069 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnce3dd56f2016-06-01 10:37:1112070
tfarina42834112016-09-22 13:38:2012071 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112072 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12073 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:1112074
bnc691fda62016-08-12 00:43:1612075 const HttpResponseInfo* response = trans.GetResponseInfo();
bnce3dd56f2016-06-01 10:37:1112076 ASSERT_TRUE(response);
12077 ASSERT_TRUE(response->headers);
12078 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12079 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212080 EXPECT_FALSE(response->was_alpn_negotiated);
bnce3dd56f2016-06-01 10:37:1112081
12082 std::string response_data;
bnc691fda62016-08-12 00:43:1612083 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:1112084 EXPECT_EQ("hello world", response_data);
12085
zhongyic4de03032017-05-19 04:07:3412086 EXPECT_TRUE(
12087 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnce3dd56f2016-06-01 10:37:1112088}
12089
bnca86731e2017-04-17 12:31:2812090// HTTP/2 Alternative Services should be disabled by default.
bnc8bef8da22016-05-30 01:28:2512091// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:0112092TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:2512093 DisableHTTP2AlternativeServicesWithDifferentHost) {
bnca86731e2017-04-17 12:31:2812094 session_deps_.enable_http2_alternative_service = false;
bncb26024382016-06-29 02:39:4512095
bnc8bef8da22016-05-30 01:28:2512096 HttpRequestInfo request;
12097 request.method = "GET";
bncb26024382016-06-29 02:39:4512098 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2512099 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012100 request.traffic_annotation =
12101 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8bef8da22016-05-30 01:28:2512102
12103 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12104 StaticSocketDataProvider first_data;
12105 first_data.set_connect_data(mock_connect);
12106 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512107 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612108 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512109 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2512110
12111 MockRead data_reads[] = {
12112 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12113 MockRead(ASYNC, OK),
12114 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112115 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnc8bef8da22016-05-30 01:28:2512116 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12117
12118 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12119
bnc525e175a2016-06-20 12:36:4012120 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2512121 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112122 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
12123 444);
bnc8bef8da22016-05-30 01:28:2512124 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112125 http_server_properties->SetHttp2AlternativeService(
bnc8bef8da22016-05-30 01:28:2512126 url::SchemeHostPort(request.url), alternative_service, expiration);
12127
bnc691fda62016-08-12 00:43:1612128 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc8bef8da22016-05-30 01:28:2512129 TestCompletionCallback callback;
12130
tfarina42834112016-09-22 13:38:2012131 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc8bef8da22016-05-30 01:28:2512132 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112133 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2512134}
12135
bnce3dd56f2016-06-01 10:37:1112136// Regression test for https://crbug.com/615497:
12137// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0112138TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1112139 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1112140 HttpRequestInfo request;
12141 request.method = "GET";
12142 request.url = GURL("http://www.example.org/");
12143 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012144 request.traffic_annotation =
12145 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnce3dd56f2016-06-01 10:37:1112146
12147 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12148 StaticSocketDataProvider first_data;
12149 first_data.set_connect_data(mock_connect);
12150 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
12151
12152 MockRead data_reads[] = {
12153 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
12154 MockRead(ASYNC, OK),
12155 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112156 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
bnce3dd56f2016-06-01 10:37:1112157 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
12158
12159 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12160
bnc525e175a2016-06-20 12:36:4012161 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1112162 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112163 AlternativeService alternative_service(kProtoHTTP2, "", 444);
bnce3dd56f2016-06-01 10:37:1112164 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112165 http_server_properties->SetHttp2AlternativeService(
bnce3dd56f2016-06-01 10:37:1112166 url::SchemeHostPort(request.url), alternative_service, expiration);
12167
bnc691fda62016-08-12 00:43:1612168 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnce3dd56f2016-06-01 10:37:1112169 TestCompletionCallback callback;
12170
tfarina42834112016-09-22 13:38:2012171 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnce3dd56f2016-06-01 10:37:1112172 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0112173 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1112174}
12175
bncd16676a2016-07-20 16:23:0112176TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0812177 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0912178 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012179 HttpServerProperties* http_server_properties =
12180 session->http_server_properties();
bncb26024382016-06-29 02:39:4512181 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc3472afd2016-11-17 15:27:2112182 AlternativeService alternative_service(kProtoQUIC, "", 80);
bnc4f575852015-10-14 18:35:0812183 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112184 http_server_properties->SetQuicAlternativeService(
12185 test_server, alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212186 session->params().quic_params.supported_versions);
zhongyic4de03032017-05-19 04:07:3412187 EXPECT_EQ(
12188 1u,
12189 http_server_properties->GetAlternativeServiceInfos(test_server).size());
bnc4f575852015-10-14 18:35:0812190
12191 // Send a clear header.
12192 MockRead data_reads[] = {
12193 MockRead("HTTP/1.1 200 OK\r\n"),
12194 MockRead("Alt-Svc: clear\r\n"),
12195 MockRead("\r\n"),
12196 MockRead("hello world"),
12197 MockRead(SYNCHRONOUS, OK),
12198 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112199 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bnc4f575852015-10-14 18:35:0812200 session_deps_.socket_factory->AddSocketDataProvider(&data);
12201
bncb26024382016-06-29 02:39:4512202 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912203 ssl.ssl_info.cert =
12204 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12205 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512206 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12207
bnc4f575852015-10-14 18:35:0812208 HttpRequestInfo request;
12209 request.method = "GET";
bncb26024382016-06-29 02:39:4512210 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012211 request.traffic_annotation =
12212 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc4f575852015-10-14 18:35:0812213
12214 TestCompletionCallback callback;
12215
bnc691fda62016-08-12 00:43:1612216 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc4f575852015-10-14 18:35:0812217
tfarina42834112016-09-22 13:38:2012218 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112219 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0812220
bnc691fda62016-08-12 00:43:1612221 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212222 ASSERT_TRUE(response);
12223 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0812224 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12225 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212226 EXPECT_FALSE(response->was_alpn_negotiated);
bnc4f575852015-10-14 18:35:0812227
12228 std::string response_data;
bnc691fda62016-08-12 00:43:1612229 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bnc4f575852015-10-14 18:35:0812230 EXPECT_EQ("hello world", response_data);
12231
zhongyic4de03032017-05-19 04:07:3412232 EXPECT_TRUE(
12233 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bnc4f575852015-10-14 18:35:0812234}
12235
bncd16676a2016-07-20 16:23:0112236TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5212237 MockRead data_reads[] = {
12238 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312239 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
12240 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5212241 MockRead("hello world"),
12242 MockRead(SYNCHRONOUS, OK),
12243 };
12244
12245 HttpRequestInfo request;
12246 request.method = "GET";
bncb26024382016-06-29 02:39:4512247 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012248 request.traffic_annotation =
12249 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bncc958faa2015-07-31 18:14:5212250
Ryan Sleevib8d7ea02018-05-07 20:01:0112251 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
bncc958faa2015-07-31 18:14:5212252 session_deps_.socket_factory->AddSocketDataProvider(&data);
12253
bncb26024382016-06-29 02:39:4512254 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912255 ssl.ssl_info.cert =
12256 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12257 ASSERT_TRUE(ssl.ssl_info.cert);
bncb26024382016-06-29 02:39:4512258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12259
bncc958faa2015-07-31 18:14:5212260 TestCompletionCallback callback;
12261
danakj1fd259a02016-04-16 03:17:0912262 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1612263 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bncc958faa2015-07-31 18:14:5212264
tfarina42834112016-09-22 13:38:2012265 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112266 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5212267
bncb26024382016-06-29 02:39:4512268 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4012269 HttpServerProperties* http_server_properties =
12270 session->http_server_properties();
zhongyic4de03032017-05-19 04:07:3412271 EXPECT_TRUE(
12272 http_server_properties->GetAlternativeServiceInfos(test_server).empty());
bncc958faa2015-07-31 18:14:5212273
robpercival214763f2016-07-01 23:27:0112274 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5212275
bnc691fda62016-08-12 00:43:1612276 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212277 ASSERT_TRUE(response);
12278 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5212279 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12280 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212281 EXPECT_FALSE(response->was_alpn_negotiated);
bncc958faa2015-07-31 18:14:5212282
12283 std::string response_data;
bnc691fda62016-08-12 00:43:1612284 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
bncc958faa2015-07-31 18:14:5212285 EXPECT_EQ("hello world", response_data);
12286
zhongyic4de03032017-05-19 04:07:3412287 AlternativeServiceInfoVector alternative_service_info_vector =
12288 http_server_properties->GetAlternativeServiceInfos(test_server);
12289 ASSERT_EQ(2u, alternative_service_info_vector.size());
12290
12291 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
12292 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412293 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412294 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
12295 1234);
12296 EXPECT_EQ(alternative_service_2,
zhongyi422ce352017-06-09 23:28:5412297 alternative_service_info_vector[1].alternative_service());
bncc958faa2015-07-31 18:14:5212298}
12299
bncd16676a2016-07-20 16:23:0112300TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612301 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212302 HostPortPair alternative("alternative.example.org", 443);
12303 std::string origin_url = "https://origin.example.org:443";
12304 std::string alternative_url = "https://alternative.example.org:443";
12305
12306 // Negotiate HTTP/1.1 with alternative.example.org.
12307 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612308 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212309 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12310
12311 // HTTP/1.1 data for request.
12312 MockWrite http_writes[] = {
12313 MockWrite("GET / HTTP/1.1\r\n"
12314 "Host: alternative.example.org\r\n"
12315 "Connection: keep-alive\r\n\r\n"),
12316 };
12317
12318 MockRead http_reads[] = {
12319 MockRead("HTTP/1.1 200 OK\r\n"
12320 "Content-Type: text/html; charset=iso-8859-1\r\n"
12321 "Content-Length: 40\r\n\r\n"
12322 "first HTTP/1.1 response from alternative"),
12323 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112324 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212325 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12326
12327 StaticSocketDataProvider data_refused;
12328 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12329 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12330
zhongyi3d4a55e72016-04-22 20:36:4612331 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0912332 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012333 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212334 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2112335 AlternativeService alternative_service(kProtoQUIC, alternative);
zhongyi48704c182015-12-07 07:52:0212336 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112337 http_server_properties->SetQuicAlternativeService(
12338 server, alternative_service, expiration,
Nick Harper72ade192019-07-17 03:30:4212339 HttpNetworkSession::Params().quic_params.supported_versions);
zhongyi48704c182015-12-07 07:52:0212340 // Mark the QUIC alternative service as broken.
12341 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
12342
zhongyi48704c182015-12-07 07:52:0212343 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612344 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212345 request.method = "GET";
12346 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012347 request.traffic_annotation =
12348 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12349
zhongyi48704c182015-12-07 07:52:0212350 TestCompletionCallback callback;
12351 NetErrorDetails details;
12352 EXPECT_FALSE(details.quic_broken);
12353
tfarina42834112016-09-22 13:38:2012354 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612355 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212356 EXPECT_TRUE(details.quic_broken);
12357}
12358
bncd16676a2016-07-20 16:23:0112359TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4612360 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0212361 HostPortPair alternative1("alternative1.example.org", 443);
12362 HostPortPair alternative2("alternative2.example.org", 443);
12363 std::string origin_url = "https://origin.example.org:443";
12364 std::string alternative_url1 = "https://alternative1.example.org:443";
12365 std::string alternative_url2 = "https://alternative2.example.org:443";
12366
12367 // Negotiate HTTP/1.1 with alternative1.example.org.
12368 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612369 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0212370 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12371
12372 // HTTP/1.1 data for request.
12373 MockWrite http_writes[] = {
12374 MockWrite("GET / HTTP/1.1\r\n"
12375 "Host: alternative1.example.org\r\n"
12376 "Connection: keep-alive\r\n\r\n"),
12377 };
12378
12379 MockRead http_reads[] = {
12380 MockRead("HTTP/1.1 200 OK\r\n"
12381 "Content-Type: text/html; charset=iso-8859-1\r\n"
12382 "Content-Length: 40\r\n\r\n"
12383 "first HTTP/1.1 response from alternative1"),
12384 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112385 StaticSocketDataProvider http_data(http_reads, http_writes);
zhongyi48704c182015-12-07 07:52:0212386 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12387
12388 StaticSocketDataProvider data_refused;
12389 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
12390 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
12391
danakj1fd259a02016-04-16 03:17:0912392 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4012393 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0212394 session->http_server_properties();
12395
zhongyi3d4a55e72016-04-22 20:36:4612396 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0212397 AlternativeServiceInfoVector alternative_service_info_vector;
12398 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
12399
bnc3472afd2016-11-17 15:27:2112400 AlternativeService alternative_service1(kProtoQUIC, alternative1);
zhongyie537a002017-06-27 16:48:2112401 alternative_service_info_vector.push_back(
12402 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12403 alternative_service1, expiration,
Nick Harper72ade192019-07-17 03:30:4212404 session->params().quic_params.supported_versions));
bnc3472afd2016-11-17 15:27:2112405 AlternativeService alternative_service2(kProtoQUIC, alternative2);
zhongyie537a002017-06-27 16:48:2112406 alternative_service_info_vector.push_back(
12407 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
12408 alternative_service2, expiration,
Nick Harper72ade192019-07-17 03:30:4212409 session->params().quic_params.supported_versions));
zhongyi48704c182015-12-07 07:52:0212410
12411 http_server_properties->SetAlternativeServices(
zhongyi3d4a55e72016-04-22 20:36:4612412 server, alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0212413
12414 // Mark one of the QUIC alternative service as broken.
12415 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
zhongyic4de03032017-05-19 04:07:3412416 EXPECT_EQ(2u,
12417 http_server_properties->GetAlternativeServiceInfos(server).size());
zhongyi48704c182015-12-07 07:52:0212418
zhongyi48704c182015-12-07 07:52:0212419 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4612420 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
zhongyi48704c182015-12-07 07:52:0212421 request.method = "GET";
12422 request.url = GURL(origin_url);
Ramin Halavatib5e433e62018-02-07 07:41:1012423 request.traffic_annotation =
12424 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12425
zhongyi48704c182015-12-07 07:52:0212426 TestCompletionCallback callback;
12427 NetErrorDetails details;
12428 EXPECT_FALSE(details.quic_broken);
12429
tfarina42834112016-09-22 13:38:2012430 trans.Start(&request, callback.callback(), NetLogWithSource());
bnc691fda62016-08-12 00:43:1612431 trans.PopulateNetErrorDetails(&details);
zhongyi48704c182015-12-07 07:52:0212432 EXPECT_FALSE(details.quic_broken);
12433}
12434
bncd16676a2016-07-20 16:23:0112435TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4212436 HttpRequestInfo request;
12437 request.method = "GET";
bncb26024382016-06-29 02:39:4512438 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012439 request.traffic_annotation =
12440 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]564b4912010-03-09 16:30:4212441
[email protected]d973e99a2012-02-17 21:02:3612442 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4212443 StaticSocketDataProvider first_data;
12444 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712445 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4512446 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612447 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512448 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4212449
12450 MockRead data_reads[] = {
12451 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12452 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612453 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4212454 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112455 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712456 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4212457
danakj1fd259a02016-04-16 03:17:0912458 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4212459
bnc525e175a2016-06-20 12:36:4012460 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312461 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4612462 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1112463 // Port must be < 1024, or the header will be ignored (since initial port was
12464 // port 80 (another restricted port).
zhongyie537a002017-06-27 16:48:2112465 // Port is ignored by MockConnect anyway.
12466 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12467 666);
bnc7dc7e1b42015-07-28 14:43:1212468 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112469 http_server_properties->SetHttp2AlternativeService(
12470 server, alternative_service, expiration);
[email protected]564b4912010-03-09 16:30:4212471
bnc691fda62016-08-12 00:43:1612472 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112473 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4212474
tfarina42834112016-09-22 13:38:2012475 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112476 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12477 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4212478
bnc691fda62016-08-12 00:43:1612479 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212480 ASSERT_TRUE(response);
12481 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4212482 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12483
12484 std::string response_data;
bnc691fda62016-08-12 00:43:1612485 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4212486 EXPECT_EQ("hello world", response_data);
12487
zhongyic4de03032017-05-19 04:07:3412488 const AlternativeServiceInfoVector alternative_service_info_vector =
12489 http_server_properties->GetAlternativeServiceInfos(server);
12490 ASSERT_EQ(1u, alternative_service_info_vector.size());
12491 EXPECT_EQ(alternative_service,
zhongyi422ce352017-06-09 23:28:5412492 alternative_service_info_vector[0].alternative_service());
zhongyic4de03032017-05-19 04:07:3412493 EXPECT_TRUE(
12494 http_server_properties->IsAlternativeServiceBroken(alternative_service));
[email protected]564b4912010-03-09 16:30:4212495}
12496
bnc55ff9da2015-08-19 18:42:3512497// Ensure that we are not allowed to redirect traffic via an alternate protocol
12498// to an unrestricted (port >= 1024) when the original traffic was on a
12499// restricted port (port < 1024). Ensure that we can redirect in all other
12500// cases.
bncd16676a2016-07-20 16:23:0112501TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1112502 HttpRequestInfo restricted_port_request;
12503 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512504 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112505 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012506 restricted_port_request.traffic_annotation =
12507 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112508
[email protected]d973e99a2012-02-17 21:02:3612509 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112510 StaticSocketDataProvider first_data;
12511 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712512 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112513
12514 MockRead data_reads[] = {
12515 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12516 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612517 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112518 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112519 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712520 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512521 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612522 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512523 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112524
danakj1fd259a02016-04-16 03:17:0912525 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112526
bnc525e175a2016-06-20 12:36:4012527 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312528 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112529 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112530 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12531 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212532 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112533 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612534 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012535 expiration);
[email protected]3912662a32011-10-04 00:51:1112536
bnc691fda62016-08-12 00:43:1612537 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112538 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112539
tfarina42834112016-09-22 13:38:2012540 int rv = trans.Start(&restricted_port_request, callback.callback(),
12541 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112542 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112543 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0112544 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1912545}
[email protected]3912662a32011-10-04 00:51:1112546
bnc55ff9da2015-08-19 18:42:3512547// Ensure that we are allowed to redirect traffic via an alternate protocol to
12548// an unrestricted (port >= 1024) when the original traffic was on a restricted
12549// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0112550TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0712551 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1912552
12553 HttpRequestInfo restricted_port_request;
12554 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512555 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1912556 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012557 restricted_port_request.traffic_annotation =
12558 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]c54c6962013-02-01 04:53:1912559
12560 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
12561 StaticSocketDataProvider first_data;
12562 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712563 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1912564
12565 MockRead data_reads[] = {
12566 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12567 MockRead("hello world"),
12568 MockRead(ASYNC, OK),
12569 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112570 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712571 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512572 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612573 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512574 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1912575
danakj1fd259a02016-04-16 03:17:0912576 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1912577
bnc525e175a2016-06-20 12:36:4012578 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1912579 session->http_server_properties();
12580 const int kUnrestrictedAlternatePort = 1024;
bnc3472afd2016-11-17 15:27:2112581 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12582 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212583 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112584 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612585 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012586 expiration);
[email protected]c54c6962013-02-01 04:53:1912587
bnc691fda62016-08-12 00:43:1612588 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]c54c6962013-02-01 04:53:1912589 TestCompletionCallback callback;
12590
tfarina42834112016-09-22 13:38:2012591 EXPECT_EQ(ERR_IO_PENDING,
12592 trans.Start(&restricted_port_request, callback.callback(),
12593 NetLogWithSource()));
[email protected]c54c6962013-02-01 04:53:1912594 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0112595 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112596}
12597
bnc55ff9da2015-08-19 18:42:3512598// Ensure that we are not allowed to redirect traffic via an alternate protocol
12599// to an unrestricted (port >= 1024) when the original traffic was on a
12600// restricted port (port < 1024). Ensure that we can redirect in all other
12601// cases.
bncd16676a2016-07-20 16:23:0112602TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1112603 HttpRequestInfo restricted_port_request;
12604 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512605 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1112606 restricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012607 restricted_port_request.traffic_annotation =
12608 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112609
[email protected]d973e99a2012-02-17 21:02:3612610 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112611 StaticSocketDataProvider first_data;
12612 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712613 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112614
12615 MockRead data_reads[] = {
12616 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12617 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612618 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112619 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112620 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712621 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112622
bncb26024382016-06-29 02:39:4512623 SSLSocketDataProvider ssl(ASYNC, OK);
12624 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12625
danakj1fd259a02016-04-16 03:17:0912626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112627
bnc525e175a2016-06-20 12:36:4012628 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312629 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112630 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112631 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12632 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212633 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112634 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612635 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012636 expiration);
[email protected]3912662a32011-10-04 00:51:1112637
bnc691fda62016-08-12 00:43:1612638 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112639 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112640
tfarina42834112016-09-22 13:38:2012641 int rv = trans.Start(&restricted_port_request, callback.callback(),
12642 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112643 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112644 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112645 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112646}
12647
bnc55ff9da2015-08-19 18:42:3512648// Ensure that we are not allowed to redirect traffic via an alternate protocol
12649// to an unrestricted (port >= 1024) when the original traffic was on a
12650// restricted port (port < 1024). Ensure that we can redirect in all other
12651// cases.
bncd16676a2016-07-20 16:23:0112652TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1112653 HttpRequestInfo unrestricted_port_request;
12654 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512655 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112656 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012657 unrestricted_port_request.traffic_annotation =
12658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112659
[email protected]d973e99a2012-02-17 21:02:3612660 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112661 StaticSocketDataProvider first_data;
12662 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712663 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112664
12665 MockRead data_reads[] = {
12666 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12667 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612668 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112669 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112670 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712671 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4512672 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612673 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512674 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1112675
danakj1fd259a02016-04-16 03:17:0912676 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112677
bnc525e175a2016-06-20 12:36:4012678 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312679 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1112680 const int kRestrictedAlternatePort = 80;
bnc3472afd2016-11-17 15:27:2112681 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12682 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212683 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112684 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612685 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012686 expiration);
[email protected]3912662a32011-10-04 00:51:1112687
bnc691fda62016-08-12 00:43:1612688 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112689 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112690
bnc691fda62016-08-12 00:43:1612691 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012692 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112694 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0112695 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112696}
12697
bnc55ff9da2015-08-19 18:42:3512698// Ensure that we are not allowed to redirect traffic via an alternate protocol
12699// to an unrestricted (port >= 1024) when the original traffic was on a
12700// restricted port (port < 1024). Ensure that we can redirect in all other
12701// cases.
bncd16676a2016-07-20 16:23:0112702TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1112703 HttpRequestInfo unrestricted_port_request;
12704 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4512705 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1112706 unrestricted_port_request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1012707 unrestricted_port_request.traffic_annotation =
12708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]3912662a32011-10-04 00:51:1112709
[email protected]d973e99a2012-02-17 21:02:3612710 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1112711 StaticSocketDataProvider first_data;
12712 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712713 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1112714
12715 MockRead data_reads[] = {
12716 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12717 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612718 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1112719 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112720 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712721 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1112722
bncb26024382016-06-29 02:39:4512723 SSLSocketDataProvider ssl(ASYNC, OK);
12724 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12725
danakj1fd259a02016-04-16 03:17:0912726 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1112727
bnc525e175a2016-06-20 12:36:4012728 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5312729 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2212730 const int kUnrestrictedAlternatePort = 1025;
bnc3472afd2016-11-17 15:27:2112731 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12732 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1212733 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112734 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612735 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5012736 expiration);
[email protected]3912662a32011-10-04 00:51:1112737
bnc691fda62016-08-12 00:43:1612738 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4112739 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1112740
bnc691fda62016-08-12 00:43:1612741 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
tfarina42834112016-09-22 13:38:2012742 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112743 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1112744 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0112745 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1112746}
12747
bnc55ff9da2015-08-19 18:42:3512748// Ensure that we are not allowed to redirect traffic via an alternate protocol
Xida Chen9bfe0b62018-04-24 19:52:2112749// to an unsafe port, and that we resume the second HttpStreamFactory::Job once
12750// the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0112751TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0212752 HttpRequestInfo request;
12753 request.method = "GET";
bncce36dca22015-04-21 22:11:2312754 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012755 request.traffic_annotation =
12756 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]eb6234e2012-01-19 01:50:0212757
12758 // The alternate protocol request will error out before we attempt to connect,
12759 // so only the standard HTTP request will try to connect.
12760 MockRead data_reads[] = {
12761 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
12762 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0612763 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0212764 };
Ryan Sleevib8d7ea02018-05-07 20:01:0112765 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712766 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0212767
danakj1fd259a02016-04-16 03:17:0912768 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0212769
bnc525e175a2016-06-20 12:36:4012770 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0212771 session->http_server_properties();
12772 const int kUnsafePort = 7;
bnc3472afd2016-11-17 15:27:2112773 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
12774 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1212775 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2112776 http_server_properties->SetHttp2AlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4612777 url::SchemeHostPort(request.url), alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0212778
bnc691fda62016-08-12 00:43:1612779 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]eb6234e2012-01-19 01:50:0212780 TestCompletionCallback callback;
12781
tfarina42834112016-09-22 13:38:2012782 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112783 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0212784 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0112785 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212786
bnc691fda62016-08-12 00:43:1612787 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212788 ASSERT_TRUE(response);
12789 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0212790 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12791
12792 std::string response_data;
bnc691fda62016-08-12 00:43:1612793 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0212794 EXPECT_EQ("hello world", response_data);
12795}
12796
bncd16676a2016-07-20 16:23:0112797TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5412798 HttpRequestInfo request;
12799 request.method = "GET";
bncb26024382016-06-29 02:39:4512800 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012801 request.traffic_annotation =
12802 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5412803
12804 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212805 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312806 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212807 MockRead("\r\n"),
12808 MockRead("hello world"),
12809 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12810 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5412811
Ryan Sleevib8d7ea02018-05-07 20:01:0112812 StaticSocketDataProvider first_transaction(data_reads,
12813 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0712814 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4512815 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612816 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4512817 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5412818
bnc032658ba2016-09-26 18:17:1512819 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5412820
Ryan Hamilton0239aac2018-05-19 00:03:1312821 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4512822 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4112823 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5412824
Raul Tambre94493c652019-03-11 17:18:3512825 spdy::SpdySerializedFrame resp(
12826 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1312827 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5412828 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112829 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5412830 };
12831
Ryan Sleevib8d7ea02018-05-07 20:01:0112832 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0712833 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5412834
[email protected]d973e99a2012-02-17 21:02:3612835 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0112836 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5512837 hanging_non_alternate_protocol_socket.set_connect_data(
12838 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0712839 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5512840 &hanging_non_alternate_protocol_socket);
12841
[email protected]49639fa2011-12-20 23:22:4112842 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5412843
danakj1fd259a02016-04-16 03:17:0912844 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5812845 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1912846 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412847
tfarina42834112016-09-22 13:38:2012848 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112849 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12850 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412851
12852 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212853 ASSERT_TRUE(response);
12854 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5412855 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12856
12857 std::string response_data;
robpercival214763f2016-07-01 23:27:0112858 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412859 EXPECT_EQ("hello world", response_data);
12860
bnc87dcefc2017-05-25 12:47:5812861 trans =
Jeremy Roman0579ed62017-08-29 15:56:1912862 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5412863
tfarina42834112016-09-22 13:38:2012864 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112865 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12866 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412867
12868 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212869 ASSERT_TRUE(response);
12870 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212871 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5312872 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212873 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5412874
robpercival214763f2016-07-01 23:27:0112875 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5412876 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5412877}
12878
bncd16676a2016-07-20 16:23:0112879TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5512880 HttpRequestInfo request;
12881 request.method = "GET";
bncb26024382016-06-29 02:39:4512882 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1012883 request.traffic_annotation =
12884 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5512885
bncb26024382016-06-29 02:39:4512886 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5512887 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5212888 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4312889 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5212890 MockRead("\r\n"),
12891 MockRead("hello world"),
12892 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
12893 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5512894 };
12895
Ryan Sleevib8d7ea02018-05-07 20:01:0112896 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
bncb26024382016-06-29 02:39:4512897 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5512898
bncb26024382016-06-29 02:39:4512899 SSLSocketDataProvider ssl_http11(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4912900 ssl_http11.ssl_info.cert =
12901 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
12902 ASSERT_TRUE(ssl_http11.ssl_info.cert);
bncb26024382016-06-29 02:39:4512903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
12904
12905 // Second transaction starts an alternative and a non-alternative Job.
12906 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3612907 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0112908 StaticSocketDataProvider hanging_socket1;
mmenkecc2298e2015-12-07 18:20:1812909 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1812910 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
12911
Ryan Sleevib8d7ea02018-05-07 20:01:0112912 StaticSocketDataProvider hanging_socket2;
mmenkecc2298e2015-12-07 18:20:1812913 hanging_socket2.set_connect_data(never_finishing_connect);
12914 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5512915
bncb26024382016-06-29 02:39:4512916 // Third transaction starts an alternative and a non-alternative job.
12917 // The non-alternative job hangs, but the alternative one succeeds.
12918 // The second transaction, still pending, binds to this socket.
Ryan Hamilton0239aac2018-05-19 00:03:1312919 spdy::SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4512920 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1312921 spdy::SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4512922 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5512923 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4112924 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5512925 };
Raul Tambre94493c652019-03-11 17:18:3512926 spdy::SpdySerializedFrame resp1(
12927 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1312928 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
Raul Tambre94493c652019-03-11 17:18:3512929 spdy::SpdySerializedFrame resp2(
12930 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1312931 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5512932 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112933 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
12934 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1312935 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5512936 };
12937
Ryan Sleevib8d7ea02018-05-07 20:01:0112938 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0712939 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5512940
bnc032658ba2016-09-26 18:17:1512941 AddSSLSocketData();
bncb26024382016-06-29 02:39:4512942
Ryan Sleevib8d7ea02018-05-07 20:01:0112943 StaticSocketDataProvider hanging_socket3;
mmenkecc2298e2015-12-07 18:20:1812944 hanging_socket3.set_connect_data(never_finishing_connect);
12945 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5512946
danakj1fd259a02016-04-16 03:17:0912947 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4112948 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5012949 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5512950
tfarina42834112016-09-22 13:38:2012951 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112952 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12953 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5512954
12955 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5212956 ASSERT_TRUE(response);
12957 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5512958 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12959
12960 std::string response_data;
robpercival214763f2016-07-01 23:27:0112961 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512962 EXPECT_EQ("hello world", response_data);
12963
[email protected]49639fa2011-12-20 23:22:4112964 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5012965 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2012966 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112967 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5512968
[email protected]49639fa2011-12-20 23:22:4112969 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5012970 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2012971 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0112972 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5512973
robpercival214763f2016-07-01 23:27:0112974 EXPECT_THAT(callback2.WaitForResult(), IsOk());
12975 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5512976
12977 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5212978 ASSERT_TRUE(response);
12979 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212980 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5512981 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212982 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0112983 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512984 EXPECT_EQ("hello!", response_data);
12985
12986 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5212987 ASSERT_TRUE(response);
12988 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212989 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5512990 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5212991 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0112992 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5512993 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5512994}
12995
bncd16676a2016-07-20 16:23:0112996TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
Bence Békybcae37092018-06-12 04:18:5312997 session_deps_.host_resolver->set_synchronous_mode(true);
12998
[email protected]2d6728692011-03-12 01:39:5512999 HttpRequestInfo request;
13000 request.method = "GET";
bncb26024382016-06-29 02:39:4513001 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013002 request.traffic_annotation =
13003 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2d6728692011-03-12 01:39:5513004
13005 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213006 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313007 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213008 MockRead("\r\n"),
13009 MockRead("hello world"),
13010 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13011 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5513012 };
13013
Ryan Sleevib8d7ea02018-05-07 20:01:0113014 StaticSocketDataProvider first_transaction(data_reads,
13015 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713016 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5513017
[email protected]8ddf8322012-02-23 18:08:0613018 SSLSocketDataProvider ssl(ASYNC, OK);
Ryan Sleevi4f832092017-11-21 23:25:4913019 ssl.ssl_info.cert =
13020 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
13021 ASSERT_TRUE(ssl.ssl_info.cert);
[email protected]bb88e1d32013-05-03 23:11:0713022 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513023
[email protected]d973e99a2012-02-17 21:02:3613024 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113025 StaticSocketDataProvider hanging_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513026 hanging_alternate_protocol_socket.set_connect_data(
13027 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713028 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513029 &hanging_alternate_protocol_socket);
13030
bncb26024382016-06-29 02:39:4513031 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
Ryan Sleevib8d7ea02018-05-07 20:01:0113032 StaticSocketDataProvider second_transaction(data_reads,
13033 base::span<MockWrite>());
mmenkecc2298e2015-12-07 18:20:1813034 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4513035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5513036
[email protected]49639fa2011-12-20 23:22:4113037 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5513038
danakj1fd259a02016-04-16 03:17:0913039 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813040 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913041 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513042
tfarina42834112016-09-22 13:38:2013043 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113044 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13045 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513046
13047 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213048 ASSERT_TRUE(response);
13049 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513050 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13051
13052 std::string response_data;
robpercival214763f2016-07-01 23:27:0113053 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513054 EXPECT_EQ("hello world", response_data);
13055
bnc87dcefc2017-05-25 12:47:5813056 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913057 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5513058
tfarina42834112016-09-22 13:38:2013059 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113060 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13061 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5513062
13063 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213064 ASSERT_TRUE(response);
13065 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5513066 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13067 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213068 EXPECT_FALSE(response->was_alpn_negotiated);
[email protected]2d6728692011-03-12 01:39:5513069
robpercival214763f2016-07-01 23:27:0113070 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5513071 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5513072}
13073
bnc2e884782016-08-11 19:45:1913074// Test that proxy is resolved using the origin url,
13075// regardless of the alternative server.
13076TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
13077 // Configure proxy to bypass www.example.org, which is the origin URL.
13078 ProxyConfig proxy_config;
13079 proxy_config.proxy_rules().ParseFromString("myproxy:70");
13080 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
Ramin Halavatica8d5252018-03-12 05:33:4913081 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
13082 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
bnc2e884782016-08-11 19:45:1913083
13084 CapturingProxyResolver capturing_proxy_resolver;
Jeremy Roman0579ed62017-08-29 15:56:1913085 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
bnc2e884782016-08-11 19:45:1913086 &capturing_proxy_resolver);
13087
13088 TestNetLog net_log;
13089
Bence Béky53a5aef2018-03-29 21:54:1213090 session_deps_.proxy_resolution_service =
13091 std::make_unique<ProxyResolutionService>(
13092 std::move(proxy_config_service), std::move(proxy_resolver_factory),
13093 &net_log);
bnc2e884782016-08-11 19:45:1913094
13095 session_deps_.net_log = &net_log;
13096
13097 // Configure alternative service with a hostname that is not bypassed by the
13098 // proxy.
13099 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13100 HttpServerProperties* http_server_properties =
13101 session->http_server_properties();
13102 url::SchemeHostPort server("https", "www.example.org", 443);
13103 HostPortPair alternative("www.example.com", 443);
bnc3472afd2016-11-17 15:27:2113104 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc2e884782016-08-11 19:45:1913105 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2113106 http_server_properties->SetHttp2AlternativeService(
13107 server, alternative_service, expiration);
bnc2e884782016-08-11 19:45:1913108
13109 // Non-alternative job should hang.
13110 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113111 StaticSocketDataProvider hanging_alternate_protocol_socket;
bnc2e884782016-08-11 19:45:1913112 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
13113 session_deps_.socket_factory->AddSocketDataProvider(
13114 &hanging_alternate_protocol_socket);
13115
bnc032658ba2016-09-26 18:17:1513116 AddSSLSocketData();
bnc2e884782016-08-11 19:45:1913117
13118 HttpRequestInfo request;
13119 request.method = "GET";
13120 request.url = GURL("https://www.example.org/");
13121 request.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1013122 request.traffic_annotation =
13123 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc2e884782016-08-11 19:45:1913124
Ryan Hamilton0239aac2018-05-19 00:03:1313125 spdy::SpdySerializedFrame req(
bnc2e884782016-08-11 19:45:1913126 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
13127
13128 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
13129
Ryan Hamilton0239aac2018-05-19 00:03:1313130 spdy::SpdySerializedFrame resp(
13131 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
13132 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc2e884782016-08-11 19:45:1913133 MockRead spdy_reads[] = {
13134 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
13135 };
13136
Ryan Sleevib8d7ea02018-05-07 20:01:0113137 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
bnc2e884782016-08-11 19:45:1913138 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
13139
13140 TestCompletionCallback callback;
13141
13142 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13143
tfarina42834112016-09-22 13:38:2013144 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc2e884782016-08-11 19:45:1913145 EXPECT_THAT(callback.GetResult(rv), IsOk());
13146
13147 const HttpResponseInfo* response = trans.GetResponseInfo();
13148 ASSERT_TRUE(response);
13149 ASSERT_TRUE(response->headers);
13150 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
13151 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213152 EXPECT_TRUE(response->was_alpn_negotiated);
bnc2e884782016-08-11 19:45:1913153
13154 std::string response_data;
13155 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
13156 EXPECT_EQ("hello!", response_data);
13157
13158 // Origin host bypasses proxy, no resolution should have happened.
13159 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
13160}
13161
bncd16676a2016-07-20 16:23:0113162TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1113163 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4213164 proxy_config.set_auto_detect(true);
13165 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1113166
sammc5dd160c2015-04-02 02:43:1313167 CapturingProxyResolver capturing_proxy_resolver;
Ramin Halavatica8d5252018-03-12 05:33:4913168 session_deps_.proxy_resolution_service =
13169 std::make_unique<ProxyResolutionService>(
13170 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
13171 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
13172 std::make_unique<CapturingProxyResolverFactory>(
13173 &capturing_proxy_resolver),
13174 nullptr);
vishal.b62985ca92015-04-17 08:45:5113175 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0713176 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1113177
13178 HttpRequestInfo request;
13179 request.method = "GET";
bncb26024382016-06-29 02:39:4513180 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013181 request.traffic_annotation =
13182 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]631f1322010-04-30 17:59:1113183
13184 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213185 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313186 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213187 MockRead("\r\n"),
13188 MockRead("hello world"),
13189 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
13190 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1113191 };
13192
Ryan Sleevib8d7ea02018-05-07 20:01:0113193 StaticSocketDataProvider first_transaction(data_reads,
13194 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713195 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513196 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613197 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513198 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1113199
bnc032658ba2016-09-26 18:17:1513200 AddSSLSocketData();
[email protected]631f1322010-04-30 17:59:1113201
Ryan Hamilton0239aac2018-05-19 00:03:1313202 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513203 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1113204 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1313205 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2513206 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13207 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1313208 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4113209 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1113210 };
13211
[email protected]d911f1b2010-05-05 22:39:4213212 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
13213
Raul Tambre94493c652019-03-11 17:18:3513214 spdy::SpdySerializedFrame resp(
13215 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313216 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1113217 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113218 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
13219 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1113220 };
13221
Ryan Sleevib8d7ea02018-05-07 20:01:0113222 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713223 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1113224
[email protected]d973e99a2012-02-17 21:02:3613225 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
Ryan Sleevib8d7ea02018-05-07 20:01:0113226 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
[email protected]2d6728692011-03-12 01:39:5513227 hanging_non_alternate_protocol_socket.set_connect_data(
13228 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0713229 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5513230 &hanging_non_alternate_protocol_socket);
13231
[email protected]49639fa2011-12-20 23:22:4113232 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1113233
danakj1fd259a02016-04-16 03:17:0913234 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5813235 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913236 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113237
tfarina42834112016-09-22 13:38:2013238 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
mmenkea2dcd3bf2016-08-16 21:49:4113239 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13240 EXPECT_THAT(callback.WaitForResult(), IsOk());
13241
13242 const HttpResponseInfo* response = trans->GetResponseInfo();
13243 ASSERT_TRUE(response);
13244 ASSERT_TRUE(response->headers);
13245 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
13246 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213247 EXPECT_TRUE(response->was_alpn_negotiated);
mmenkea2dcd3bf2016-08-16 21:49:4113248
13249 std::string response_data;
13250 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
13251 EXPECT_EQ("hello world", response_data);
[email protected]631f1322010-04-30 17:59:1113252
bnc87dcefc2017-05-25 12:47:5813253 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913254 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]631f1322010-04-30 17:59:1113255
tfarina42834112016-09-22 13:38:2013256 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113257 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13258 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1113259
mmenkea2dcd3bf2016-08-16 21:49:4113260 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213261 ASSERT_TRUE(response);
13262 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213263 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313264 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213265 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]631f1322010-04-30 17:59:1113266
robpercival214763f2016-07-01 23:27:0113267 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1113268 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4513269 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
13270 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313271 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2313272 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1313273 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1113274
[email protected]029c83b62013-01-24 05:28:2013275 LoadTimingInfo load_timing_info;
13276 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
13277 TestLoadTimingNotReusedWithPac(load_timing_info,
13278 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1113279}
[email protected]631f1322010-04-30 17:59:1113280
bncd16676a2016-07-20 16:23:0113281TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4813282 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5413283 HttpRequestInfo request;
13284 request.method = "GET";
bncb26024382016-06-29 02:39:4513285 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1013286 request.traffic_annotation =
13287 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]2ff8b312010-04-26 22:20:5413288
13289 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5213290 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4313291 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5213292 MockRead("\r\n"),
13293 MockRead("hello world"),
13294 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5413295 };
13296
Ryan Sleevib8d7ea02018-05-07 20:01:0113297 StaticSocketDataProvider first_transaction(data_reads,
13298 base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0713299 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4513300 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613301 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4513302 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5413303
bnc032658ba2016-09-26 18:17:1513304 AddSSLSocketData();
[email protected]2ff8b312010-04-26 22:20:5413305
Ryan Hamilton0239aac2018-05-19 00:03:1313306 spdy::SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4513307 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113308 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5413309
Raul Tambre94493c652019-03-11 17:18:3513310 spdy::SpdySerializedFrame resp(
13311 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1313312 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5413313 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113314 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5413315 };
13316
Ryan Sleevib8d7ea02018-05-07 20:01:0113317 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0713318 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5413319
[email protected]83039bb2011-12-09 18:43:5513320 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5413321
danakj1fd259a02016-04-16 03:17:0913322 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5413323
bnc87dcefc2017-05-25 12:47:5813324 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1913325 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413326
tfarina42834112016-09-22 13:38:2013327 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113328 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13329 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413330
13331 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213332 ASSERT_TRUE(response);
13333 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5413334 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13335
13336 std::string response_data;
robpercival214763f2016-07-01 23:27:0113337 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413338 EXPECT_EQ("hello world", response_data);
13339
13340 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2513341 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4013342 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1113343 PRIVACY_MODE_DISABLED,
13344 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2713345 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5213346 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]02b0c342010-09-25 21:09:3813347
bnc87dcefc2017-05-25 12:47:5813348 trans =
Jeremy Roman0579ed62017-08-29 15:56:1913349 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]2ff8b312010-04-26 22:20:5413350
tfarina42834112016-09-22 13:38:2013351 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0113352 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13353 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413354
13355 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213356 ASSERT_TRUE(response);
13357 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213358 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5313359 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5213360 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5413361
robpercival214763f2016-07-01 23:27:0113362 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5413363 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4213364}
13365
[email protected]044de0642010-06-17 10:42:1513366// GenerateAuthToken is a mighty big test.
13367// It tests all permutation of GenerateAuthToken behavior:
13368// - Synchronous and Asynchronous completion.
13369// - OK or error on completion.
13370// - Direct connection, non-authenticating proxy, and authenticating proxy.
13371// - HTTP or HTTPS backend (to include proxy tunneling).
13372// - Non-authenticating and authenticating backend.
13373//
[email protected]fe3b7dc2012-02-03 19:52:0913374// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1513375// problems generating an auth token for an authenticating proxy, we don't
13376// need to test all permutations of the backend server).
13377//
13378// The test proceeds by going over each of the configuration cases, and
13379// potentially running up to three rounds in each of the tests. The TestConfig
13380// specifies both the configuration for the test as well as the expectations
13381// for the results.
bncd16676a2016-07-20 16:23:0113382TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5013383 static const char kServer[] = "http://www.example.com";
13384 static const char kSecureServer[] = "https://www.example.com";
13385 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1513386
13387 enum AuthTiming {
13388 AUTH_NONE,
13389 AUTH_SYNC,
13390 AUTH_ASYNC,
13391 };
13392
13393 const MockWrite kGet(
13394 "GET / HTTP/1.1\r\n"
13395 "Host: www.example.com\r\n"
13396 "Connection: keep-alive\r\n\r\n");
13397 const MockWrite kGetProxy(
13398 "GET http://www.example.com/ HTTP/1.1\r\n"
13399 "Host: www.example.com\r\n"
13400 "Proxy-Connection: keep-alive\r\n\r\n");
13401 const MockWrite kGetAuth(
13402 "GET / HTTP/1.1\r\n"
13403 "Host: www.example.com\r\n"
13404 "Connection: keep-alive\r\n"
13405 "Authorization: auth_token\r\n\r\n");
13406 const MockWrite kGetProxyAuth(
13407 "GET http://www.example.com/ HTTP/1.1\r\n"
13408 "Host: www.example.com\r\n"
13409 "Proxy-Connection: keep-alive\r\n"
13410 "Proxy-Authorization: auth_token\r\n\r\n");
13411 const MockWrite kGetAuthThroughProxy(
13412 "GET http://www.example.com/ HTTP/1.1\r\n"
13413 "Host: www.example.com\r\n"
13414 "Proxy-Connection: keep-alive\r\n"
13415 "Authorization: auth_token\r\n\r\n");
13416 const MockWrite kGetAuthWithProxyAuth(
13417 "GET http://www.example.com/ HTTP/1.1\r\n"
13418 "Host: www.example.com\r\n"
13419 "Proxy-Connection: keep-alive\r\n"
13420 "Proxy-Authorization: auth_token\r\n"
13421 "Authorization: auth_token\r\n\r\n");
13422 const MockWrite kConnect(
13423 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713424 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513425 "Proxy-Connection: keep-alive\r\n\r\n");
13426 const MockWrite kConnectProxyAuth(
13427 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1713428 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1513429 "Proxy-Connection: keep-alive\r\n"
13430 "Proxy-Authorization: auth_token\r\n\r\n");
13431
13432 const MockRead kSuccess(
13433 "HTTP/1.1 200 OK\r\n"
13434 "Content-Type: text/html; charset=iso-8859-1\r\n"
13435 "Content-Length: 3\r\n\r\n"
13436 "Yes");
13437 const MockRead kFailure(
13438 "Should not be called.");
13439 const MockRead kServerChallenge(
13440 "HTTP/1.1 401 Unauthorized\r\n"
13441 "WWW-Authenticate: Mock realm=server\r\n"
13442 "Content-Type: text/html; charset=iso-8859-1\r\n"
13443 "Content-Length: 14\r\n\r\n"
13444 "Unauthorized\r\n");
13445 const MockRead kProxyChallenge(
13446 "HTTP/1.1 407 Unauthorized\r\n"
13447 "Proxy-Authenticate: Mock realm=proxy\r\n"
13448 "Proxy-Connection: close\r\n"
13449 "Content-Type: text/html; charset=iso-8859-1\r\n"
13450 "Content-Length: 14\r\n\r\n"
13451 "Unauthorized\r\n");
13452 const MockRead kProxyConnected(
13453 "HTTP/1.1 200 Connection Established\r\n\r\n");
13454
13455 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
13456 // no constructors, but the C++ compiler on Windows warns about
13457 // unspecified data in compound literals. So, moved to using constructors,
13458 // and TestRound's created with the default constructor should not be used.
13459 struct TestRound {
13460 TestRound()
Raul Tambre94493c652019-03-11 17:18:3513461 : expected_rv(ERR_UNEXPECTED),
13462 extra_write(nullptr),
13463 extra_read(nullptr) {}
Raul Tambre8335a6d2019-02-21 16:57:4313464 TestRound(const MockWrite& write_arg,
13465 const MockRead& read_arg,
[email protected]044de0642010-06-17 10:42:1513466 int expected_rv_arg)
13467 : write(write_arg),
13468 read(read_arg),
13469 expected_rv(expected_rv_arg),
Raul Tambre94493c652019-03-11 17:18:3513470 extra_write(nullptr),
13471 extra_read(nullptr) {}
[email protected]044de0642010-06-17 10:42:1513472 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
13473 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0113474 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1513475 : write(write_arg),
13476 read(read_arg),
13477 expected_rv(expected_rv_arg),
13478 extra_write(extra_write_arg),
13479 extra_read(extra_read_arg) {
13480 }
13481 MockWrite write;
13482 MockRead read;
13483 int expected_rv;
13484 const MockWrite* extra_write;
13485 const MockRead* extra_read;
13486 };
13487
13488 static const int kNoSSL = 500;
13489
13490 struct TestConfig {
asanka463ca4262016-11-16 02:34:3113491 int line_number;
thestig9d3bb0c2015-01-24 00:49:5113492 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1513493 AuthTiming proxy_auth_timing;
asanka463ca4262016-11-16 02:34:3113494 int first_generate_proxy_token_rv;
thestig9d3bb0c2015-01-24 00:49:5113495 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1513496 AuthTiming server_auth_timing;
asanka463ca4262016-11-16 02:34:3113497 int first_generate_server_token_rv;
[email protected]044de0642010-06-17 10:42:1513498 int num_auth_rounds;
13499 int first_ssl_round;
asankae2257db2016-10-11 22:03:1613500 TestRound rounds[4];
[email protected]044de0642010-06-17 10:42:1513501 } test_configs[] = {
asankac93076192016-10-03 15:46:0213502 // Non-authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113503 {__LINE__,
13504 nullptr,
asankac93076192016-10-03 15:46:0213505 AUTH_NONE,
13506 OK,
13507 kServer,
13508 AUTH_NONE,
13509 OK,
13510 1,
13511 kNoSSL,
13512 {TestRound(kGet, kSuccess, OK)}},
13513 // Authenticating HTTP server with a direct connection.
asanka463ca4262016-11-16 02:34:3113514 {__LINE__,
13515 nullptr,
asankac93076192016-10-03 15:46:0213516 AUTH_NONE,
13517 OK,
13518 kServer,
13519 AUTH_SYNC,
13520 OK,
13521 2,
13522 kNoSSL,
13523 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513524 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113525 {__LINE__,
13526 nullptr,
asankac93076192016-10-03 15:46:0213527 AUTH_NONE,
13528 OK,
13529 kServer,
13530 AUTH_SYNC,
13531 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613532 3,
13533 kNoSSL,
13534 {TestRound(kGet, kServerChallenge, OK),
13535 TestRound(kGet, kServerChallenge, OK),
13536 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113537 {__LINE__,
13538 nullptr,
asankae2257db2016-10-11 22:03:1613539 AUTH_NONE,
13540 OK,
13541 kServer,
13542 AUTH_SYNC,
13543 ERR_UNSUPPORTED_AUTH_SCHEME,
13544 2,
13545 kNoSSL,
13546 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113547 {__LINE__,
13548 nullptr,
asankae2257db2016-10-11 22:03:1613549 AUTH_NONE,
13550 OK,
13551 kServer,
13552 AUTH_SYNC,
13553 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
13554 2,
13555 kNoSSL,
13556 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113557 {__LINE__,
13558 kProxy,
asankae2257db2016-10-11 22:03:1613559 AUTH_SYNC,
13560 ERR_FAILED,
13561 kServer,
13562 AUTH_NONE,
13563 OK,
13564 2,
13565 kNoSSL,
13566 {TestRound(kGetProxy, kProxyChallenge, OK),
13567 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113568 {__LINE__,
13569 kProxy,
asankae2257db2016-10-11 22:03:1613570 AUTH_ASYNC,
13571 ERR_FAILED,
13572 kServer,
13573 AUTH_NONE,
13574 OK,
13575 2,
13576 kNoSSL,
13577 {TestRound(kGetProxy, kProxyChallenge, OK),
13578 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113579 {__LINE__,
13580 nullptr,
asankae2257db2016-10-11 22:03:1613581 AUTH_NONE,
13582 OK,
13583 kServer,
13584 AUTH_SYNC,
13585 ERR_FAILED,
asankac93076192016-10-03 15:46:0213586 2,
13587 kNoSSL,
13588 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613589 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113590 {__LINE__,
13591 nullptr,
asankae2257db2016-10-11 22:03:1613592 AUTH_NONE,
13593 OK,
13594 kServer,
13595 AUTH_ASYNC,
13596 ERR_FAILED,
13597 2,
13598 kNoSSL,
13599 {TestRound(kGet, kServerChallenge, OK),
13600 TestRound(kGet, kFailure, ERR_FAILED)}},
asanka463ca4262016-11-16 02:34:3113601 {__LINE__,
13602 nullptr,
asankac93076192016-10-03 15:46:0213603 AUTH_NONE,
13604 OK,
13605 kServer,
13606 AUTH_ASYNC,
13607 OK,
13608 2,
13609 kNoSSL,
13610 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513611 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113612 {__LINE__,
13613 nullptr,
asankac93076192016-10-03 15:46:0213614 AUTH_NONE,
13615 OK,
13616 kServer,
13617 AUTH_ASYNC,
13618 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613619 3,
asankac93076192016-10-03 15:46:0213620 kNoSSL,
13621 {TestRound(kGet, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613622 // The second round uses a HttpAuthHandlerMock that always succeeds.
13623 TestRound(kGet, kServerChallenge, OK),
13624 TestRound(kGetAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213625 // Non-authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113626 {__LINE__,
13627 kProxy,
asankac93076192016-10-03 15:46:0213628 AUTH_NONE,
13629 OK,
13630 kServer,
13631 AUTH_NONE,
13632 OK,
13633 1,
13634 kNoSSL,
13635 {TestRound(kGetProxy, kSuccess, OK)}},
13636 // Authenticating HTTP server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113637 {__LINE__,
13638 kProxy,
asankac93076192016-10-03 15:46:0213639 AUTH_NONE,
13640 OK,
13641 kServer,
13642 AUTH_SYNC,
13643 OK,
13644 2,
13645 kNoSSL,
13646 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513647 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_SYNC,
13654 ERR_INVALID_AUTH_CREDENTIALS,
asankae2257db2016-10-11 22:03:1613655 3,
asankac93076192016-10-03 15:46:0213656 kNoSSL,
13657 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613658 TestRound(kGetProxy, kServerChallenge, OK),
13659 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113660 {__LINE__,
13661 kProxy,
asankac93076192016-10-03 15:46:0213662 AUTH_NONE,
13663 OK,
13664 kServer,
13665 AUTH_ASYNC,
13666 OK,
13667 2,
13668 kNoSSL,
13669 {TestRound(kGetProxy, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513670 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113671 {__LINE__,
13672 kProxy,
asankac93076192016-10-03 15:46:0213673 AUTH_NONE,
13674 OK,
13675 kServer,
13676 AUTH_ASYNC,
13677 ERR_INVALID_AUTH_CREDENTIALS,
13678 2,
13679 kNoSSL,
13680 {TestRound(kGetProxy, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613681 TestRound(kGetProxy, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213682 // Non-authenticating HTTP server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113683 {__LINE__,
13684 kProxy,
asankac93076192016-10-03 15:46:0213685 AUTH_SYNC,
13686 OK,
13687 kServer,
13688 AUTH_NONE,
13689 OK,
13690 2,
13691 kNoSSL,
13692 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513693 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113694 {__LINE__,
13695 kProxy,
asankac93076192016-10-03 15:46:0213696 AUTH_SYNC,
13697 ERR_INVALID_AUTH_CREDENTIALS,
13698 kServer,
13699 AUTH_NONE,
13700 OK,
13701 2,
13702 kNoSSL,
13703 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613704 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113705 {__LINE__,
13706 kProxy,
asankac93076192016-10-03 15:46:0213707 AUTH_ASYNC,
13708 OK,
13709 kServer,
13710 AUTH_NONE,
13711 OK,
13712 2,
13713 kNoSSL,
13714 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513715 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113716 {__LINE__,
13717 kProxy,
asankac93076192016-10-03 15:46:0213718 AUTH_ASYNC,
13719 ERR_INVALID_AUTH_CREDENTIALS,
13720 kServer,
13721 AUTH_NONE,
13722 OK,
13723 2,
13724 kNoSSL,
13725 {TestRound(kGetProxy, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613726 TestRound(kGetProxy, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113727 {__LINE__,
13728 kProxy,
13729 AUTH_ASYNC,
13730 ERR_INVALID_AUTH_CREDENTIALS,
13731 kServer,
13732 AUTH_NONE,
13733 OK,
13734 3,
13735 kNoSSL,
13736 {TestRound(kGetProxy, kProxyChallenge, OK),
13737 TestRound(kGetProxy, kProxyChallenge, OK),
13738 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213739 // Authenticating HTTP server through an authenticating proxy.
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 OK,
13747 3,
13748 kNoSSL,
13749 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513750 TestRound(kGetProxyAuth, kServerChallenge, OK),
13751 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113752 {__LINE__,
13753 kProxy,
asankac93076192016-10-03 15:46:0213754 AUTH_SYNC,
13755 OK,
13756 kServer,
13757 AUTH_SYNC,
13758 ERR_INVALID_AUTH_CREDENTIALS,
13759 3,
13760 kNoSSL,
13761 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513762 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613763 TestRound(kGetProxyAuth, 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 OK,
13771 3,
13772 kNoSSL,
13773 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513774 TestRound(kGetProxyAuth, kServerChallenge, OK),
13775 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113776 {__LINE__,
13777 kProxy,
asankac93076192016-10-03 15:46:0213778 AUTH_ASYNC,
13779 OK,
13780 kServer,
13781 AUTH_SYNC,
13782 ERR_INVALID_AUTH_CREDENTIALS,
13783 3,
13784 kNoSSL,
13785 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513786 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613787 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113788 {__LINE__,
13789 kProxy,
asankac93076192016-10-03 15:46:0213790 AUTH_SYNC,
13791 OK,
13792 kServer,
13793 AUTH_ASYNC,
13794 OK,
13795 3,
13796 kNoSSL,
13797 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513798 TestRound(kGetProxyAuth, kServerChallenge, OK),
13799 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113800 {__LINE__,
13801 kProxy,
13802 AUTH_SYNC,
13803 ERR_INVALID_AUTH_CREDENTIALS,
13804 kServer,
13805 AUTH_ASYNC,
13806 OK,
13807 4,
13808 kNoSSL,
13809 {TestRound(kGetProxy, kProxyChallenge, OK),
13810 TestRound(kGetProxy, kProxyChallenge, OK),
13811 TestRound(kGetProxyAuth, kServerChallenge, OK),
13812 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
13813 {__LINE__,
13814 kProxy,
asankac93076192016-10-03 15:46:0213815 AUTH_SYNC,
13816 OK,
13817 kServer,
13818 AUTH_ASYNC,
13819 ERR_INVALID_AUTH_CREDENTIALS,
13820 3,
13821 kNoSSL,
13822 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513823 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613824 TestRound(kGetProxyAuth, 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 OK,
13832 3,
13833 kNoSSL,
13834 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513835 TestRound(kGetProxyAuth, kServerChallenge, OK),
13836 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113837 {__LINE__,
13838 kProxy,
asankac93076192016-10-03 15:46:0213839 AUTH_ASYNC,
13840 OK,
13841 kServer,
13842 AUTH_ASYNC,
13843 ERR_INVALID_AUTH_CREDENTIALS,
13844 3,
13845 kNoSSL,
13846 {TestRound(kGetProxy, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513847 TestRound(kGetProxyAuth, kServerChallenge, OK),
asankae2257db2016-10-11 22:03:1613848 TestRound(kGetProxyAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113849 {__LINE__,
13850 kProxy,
13851 AUTH_ASYNC,
13852 ERR_INVALID_AUTH_CREDENTIALS,
13853 kServer,
13854 AUTH_ASYNC,
13855 ERR_INVALID_AUTH_CREDENTIALS,
13856 4,
13857 kNoSSL,
13858 {TestRound(kGetProxy, kProxyChallenge, OK),
13859 TestRound(kGetProxy, kProxyChallenge, OK),
13860 TestRound(kGetProxyAuth, kServerChallenge, OK),
13861 TestRound(kGetProxyAuth, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213862 // Non-authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113863 {__LINE__,
13864 nullptr,
asankac93076192016-10-03 15:46:0213865 AUTH_NONE,
13866 OK,
13867 kSecureServer,
13868 AUTH_NONE,
13869 OK,
13870 1,
13871 0,
13872 {TestRound(kGet, kSuccess, OK)}},
13873 // Authenticating HTTPS server with a direct connection.
asanka463ca4262016-11-16 02:34:3113874 {__LINE__,
13875 nullptr,
asankac93076192016-10-03 15:46:0213876 AUTH_NONE,
13877 OK,
13878 kSecureServer,
13879 AUTH_SYNC,
13880 OK,
13881 2,
13882 0,
13883 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513884 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113885 {__LINE__,
13886 nullptr,
asankac93076192016-10-03 15:46:0213887 AUTH_NONE,
13888 OK,
13889 kSecureServer,
13890 AUTH_SYNC,
13891 ERR_INVALID_AUTH_CREDENTIALS,
13892 2,
13893 0,
asankae2257db2016-10-11 22:03:1613894 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113895 {__LINE__,
13896 nullptr,
asankac93076192016-10-03 15:46:0213897 AUTH_NONE,
13898 OK,
13899 kSecureServer,
13900 AUTH_ASYNC,
13901 OK,
13902 2,
13903 0,
13904 {TestRound(kGet, kServerChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513905 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113906 {__LINE__,
13907 nullptr,
asankac93076192016-10-03 15:46:0213908 AUTH_NONE,
13909 OK,
13910 kSecureServer,
13911 AUTH_ASYNC,
13912 ERR_INVALID_AUTH_CREDENTIALS,
13913 2,
13914 0,
asankae2257db2016-10-11 22:03:1613915 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213916 // Non-authenticating HTTPS server with a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113917 {__LINE__,
13918 kProxy,
asankac93076192016-10-03 15:46:0213919 AUTH_NONE,
13920 OK,
13921 kSecureServer,
13922 AUTH_NONE,
13923 OK,
13924 1,
13925 0,
13926 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
13927 // Authenticating HTTPS server through a non-authenticating proxy.
asanka463ca4262016-11-16 02:34:3113928 {__LINE__,
13929 kProxy,
asankac93076192016-10-03 15:46:0213930 AUTH_NONE,
13931 OK,
13932 kSecureServer,
13933 AUTH_SYNC,
13934 OK,
13935 2,
13936 0,
13937 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1513938 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113939 {__LINE__,
13940 kProxy,
asankac93076192016-10-03 15:46:0213941 AUTH_NONE,
13942 OK,
13943 kSecureServer,
13944 AUTH_SYNC,
13945 ERR_INVALID_AUTH_CREDENTIALS,
13946 2,
13947 0,
13948 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1613949 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113950 {__LINE__,
13951 kProxy,
asankac93076192016-10-03 15:46:0213952 AUTH_NONE,
13953 OK,
13954 kSecureServer,
13955 AUTH_ASYNC,
13956 OK,
13957 2,
13958 0,
13959 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1513960 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3113961 {__LINE__,
13962 kProxy,
asankac93076192016-10-03 15:46:0213963 AUTH_NONE,
13964 OK,
13965 kSecureServer,
13966 AUTH_ASYNC,
13967 ERR_INVALID_AUTH_CREDENTIALS,
13968 2,
13969 0,
13970 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
asankae2257db2016-10-11 22:03:1613971 TestRound(kGet, kSuccess, OK)}},
asankac93076192016-10-03 15:46:0213972 // Non-Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3113973 {__LINE__,
13974 kProxy,
asankac93076192016-10-03 15:46:0213975 AUTH_SYNC,
13976 OK,
13977 kSecureServer,
13978 AUTH_NONE,
13979 OK,
13980 2,
13981 1,
13982 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1513983 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3113984 {__LINE__,
13985 kProxy,
asankac93076192016-10-03 15:46:0213986 AUTH_SYNC,
13987 ERR_INVALID_AUTH_CREDENTIALS,
13988 kSecureServer,
13989 AUTH_NONE,
13990 OK,
13991 2,
13992 kNoSSL,
13993 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1613994 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3113995 {__LINE__,
13996 kProxy,
asankae2257db2016-10-11 22:03:1613997 AUTH_SYNC,
13998 ERR_UNSUPPORTED_AUTH_SCHEME,
13999 kSecureServer,
14000 AUTH_NONE,
14001 OK,
14002 2,
14003 kNoSSL,
14004 {TestRound(kConnect, kProxyChallenge, OK),
14005 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114006 {__LINE__,
14007 kProxy,
asankae2257db2016-10-11 22:03:1614008 AUTH_SYNC,
14009 ERR_UNEXPECTED,
14010 kSecureServer,
14011 AUTH_NONE,
14012 OK,
14013 2,
14014 kNoSSL,
14015 {TestRound(kConnect, kProxyChallenge, OK),
14016 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
asanka463ca4262016-11-16 02:34:3114017 {__LINE__,
14018 kProxy,
asankac93076192016-10-03 15:46:0214019 AUTH_ASYNC,
14020 OK,
14021 kSecureServer,
14022 AUTH_NONE,
14023 OK,
14024 2,
14025 1,
14026 {TestRound(kConnect, kProxyChallenge, OK),
[email protected]044de0642010-06-17 10:42:1514027 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
asanka463ca4262016-11-16 02:34:3114028 {__LINE__,
14029 kProxy,
asankac93076192016-10-03 15:46:0214030 AUTH_ASYNC,
14031 ERR_INVALID_AUTH_CREDENTIALS,
14032 kSecureServer,
14033 AUTH_NONE,
14034 OK,
14035 2,
14036 kNoSSL,
14037 {TestRound(kConnect, kProxyChallenge, OK),
asankae2257db2016-10-11 22:03:1614038 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
asankac93076192016-10-03 15:46:0214039 // Authenticating HTTPS server through an authenticating proxy.
asanka463ca4262016-11-16 02:34:3114040 {__LINE__,
14041 kProxy,
asankac93076192016-10-03 15:46:0214042 AUTH_SYNC,
14043 OK,
14044 kSecureServer,
14045 AUTH_SYNC,
14046 OK,
14047 3,
14048 1,
14049 {TestRound(kConnect, kProxyChallenge, OK),
14050 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14051 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514052 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114053 {__LINE__,
14054 kProxy,
asankac93076192016-10-03 15:46:0214055 AUTH_SYNC,
14056 OK,
14057 kSecureServer,
14058 AUTH_SYNC,
14059 ERR_INVALID_AUTH_CREDENTIALS,
14060 3,
14061 1,
14062 {TestRound(kConnect, kProxyChallenge, OK),
14063 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14064 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614065 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114066 {__LINE__,
14067 kProxy,
asankac93076192016-10-03 15:46:0214068 AUTH_ASYNC,
14069 OK,
14070 kSecureServer,
14071 AUTH_SYNC,
14072 OK,
14073 3,
14074 1,
14075 {TestRound(kConnect, kProxyChallenge, OK),
14076 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14077 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514078 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114079 {__LINE__,
14080 kProxy,
asankac93076192016-10-03 15:46:0214081 AUTH_ASYNC,
14082 OK,
14083 kSecureServer,
14084 AUTH_SYNC,
14085 ERR_INVALID_AUTH_CREDENTIALS,
14086 3,
14087 1,
14088 {TestRound(kConnect, kProxyChallenge, OK),
14089 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14090 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614091 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114092 {__LINE__,
14093 kProxy,
asankac93076192016-10-03 15:46:0214094 AUTH_SYNC,
14095 OK,
14096 kSecureServer,
14097 AUTH_ASYNC,
14098 OK,
14099 3,
14100 1,
14101 {TestRound(kConnect, kProxyChallenge, OK),
14102 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14103 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514104 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114105 {__LINE__,
14106 kProxy,
asankac93076192016-10-03 15:46:0214107 AUTH_SYNC,
14108 OK,
14109 kSecureServer,
14110 AUTH_ASYNC,
14111 ERR_INVALID_AUTH_CREDENTIALS,
14112 3,
14113 1,
14114 {TestRound(kConnect, kProxyChallenge, OK),
14115 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14116 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614117 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114118 {__LINE__,
14119 kProxy,
asankac93076192016-10-03 15:46:0214120 AUTH_ASYNC,
14121 OK,
14122 kSecureServer,
14123 AUTH_ASYNC,
14124 OK,
14125 3,
14126 1,
14127 {TestRound(kConnect, kProxyChallenge, OK),
14128 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14129 &kServerChallenge),
[email protected]044de0642010-06-17 10:42:1514130 TestRound(kGetAuth, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114131 {__LINE__,
14132 kProxy,
asankac93076192016-10-03 15:46:0214133 AUTH_ASYNC,
14134 OK,
14135 kSecureServer,
14136 AUTH_ASYNC,
14137 ERR_INVALID_AUTH_CREDENTIALS,
14138 3,
14139 1,
14140 {TestRound(kConnect, kProxyChallenge, OK),
14141 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14142 &kServerChallenge),
asankae2257db2016-10-11 22:03:1614143 TestRound(kGet, kSuccess, OK)}},
asanka463ca4262016-11-16 02:34:3114144 {__LINE__,
14145 kProxy,
14146 AUTH_ASYNC,
14147 ERR_INVALID_AUTH_CREDENTIALS,
14148 kSecureServer,
14149 AUTH_ASYNC,
14150 ERR_INVALID_AUTH_CREDENTIALS,
14151 4,
14152 2,
14153 {TestRound(kConnect, kProxyChallenge, OK),
14154 TestRound(kConnect, kProxyChallenge, OK),
14155 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
14156 &kServerChallenge),
14157 TestRound(kGet, kSuccess, OK)}},
[email protected]044de0642010-06-17 10:42:1514158 };
14159
asanka463ca4262016-11-16 02:34:3114160 for (const auto& test_config : test_configs) {
14161 SCOPED_TRACE(::testing::Message() << "Test config at "
14162 << test_config.line_number);
[email protected]2d01c262011-08-11 23:07:0814163 HttpAuthHandlerMock::Factory* auth_factory(
14164 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714165 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4914166 SSLInfo empty_ssl_info;
[email protected]65d34382010-07-01 18:12:2614167
14168 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1514169 if (test_config.proxy_auth_timing != AUTH_NONE) {
asanka463ca4262016-11-16 02:34:3114170 for (int n = 0; n < 3; n++) {
[email protected]2d01c262011-08-11 23:07:0814171 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14172 std::string auth_challenge = "Mock realm=proxy";
14173 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2414174 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14175 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0814176 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
tfarina42834112016-09-22 13:38:2014177 empty_ssl_info, origin,
14178 NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814179 auth_handler->SetGenerateExpectation(
14180 test_config.proxy_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114181 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
[email protected]2d01c262011-08-11 23:07:0814182 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
14183 }
[email protected]044de0642010-06-17 10:42:1514184 }
14185 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0014186 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1514187 std::string auth_challenge = "Mock realm=server";
14188 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2414189 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14190 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1514191 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014192 empty_ssl_info, origin,
14193 NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514194 auth_handler->SetGenerateExpectation(
14195 test_config.server_auth_timing == AUTH_ASYNC,
asanka463ca4262016-11-16 02:34:3114196 test_config.first_generate_server_token_rv);
[email protected]2d01c262011-08-11 23:07:0814197 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
asankae2257db2016-10-11 22:03:1614198
14199 // The second handler always succeeds. It should only be used where there
14200 // are multiple auth sessions for server auth in the same network
14201 // transaction using the same auth scheme.
14202 std::unique_ptr<HttpAuthHandlerMock> second_handler =
Jeremy Roman0579ed62017-08-29 15:56:1914203 std::make_unique<HttpAuthHandlerMock>();
asankae2257db2016-10-11 22:03:1614204 second_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
14205 empty_ssl_info, origin,
14206 NetLogWithSource());
14207 second_handler->SetGenerateExpectation(true, OK);
14208 auth_factory->AddMockHandler(second_handler.release(),
14209 HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1514210 }
14211 if (test_config.proxy_url) {
Lily Houghton8c2f97d2018-01-22 05:06:5914212 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914213 ProxyResolutionService::CreateFixed(test_config.proxy_url,
14214 TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514215 } else {
Bence Béky53a5aef2018-03-29 21:54:1214216 session_deps_.proxy_resolution_service =
14217 ProxyResolutionService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1514218 }
14219
14220 HttpRequestInfo request;
14221 request.method = "GET";
14222 request.url = GURL(test_config.server_url);
Ramin Halavatib5e433e62018-02-07 07:41:1014223 request.traffic_annotation =
14224 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]044de0642010-06-17 10:42:1514225
danakj1fd259a02016-04-16 03:17:0914226 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1514227
rchcb68dc62015-05-21 04:45:3614228 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
14229
14230 std::vector<std::vector<MockRead>> mock_reads(1);
14231 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1514232 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214233 SCOPED_TRACE(round);
[email protected]044de0642010-06-17 10:42:1514234 const TestRound& read_write_round = test_config.rounds[round];
14235
14236 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3614237 mock_reads.back().push_back(read_write_round.read);
14238 mock_writes.back().push_back(read_write_round.write);
14239
14240 // kProxyChallenge uses Proxy-Connection: close which means that the
14241 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5414242 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3614243 mock_reads.push_back(std::vector<MockRead>());
14244 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1514245 }
14246
rchcb68dc62015-05-21 04:45:3614247 if (read_write_round.extra_read) {
14248 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1514249 }
rchcb68dc62015-05-21 04:45:3614250 if (read_write_round.extra_write) {
14251 mock_writes.back().push_back(*read_write_round.extra_write);
14252 }
[email protected]044de0642010-06-17 10:42:1514253
14254 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1514255 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0714256 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1514257 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3614258 }
[email protected]044de0642010-06-17 10:42:1514259
danakj1fd259a02016-04-16 03:17:0914260 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3614261 for (size_t i = 0; i < mock_reads.size(); ++i) {
Jeremy Roman0579ed62017-08-29 15:56:1914262 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
Ryan Sleevib8d7ea02018-05-07 20:01:0114263 mock_reads[i], mock_writes[i]));
rchcb68dc62015-05-21 04:45:3614264 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3214265 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3614266 }
14267
mmenkecc2298e2015-12-07 18:20:1814268 // Transaction must be created after DataProviders, so it's destroyed before
14269 // they are as well.
14270 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14271
rchcb68dc62015-05-21 04:45:3614272 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
davidben8c7089a2017-04-17 20:38:2214273 SCOPED_TRACE(round);
rchcb68dc62015-05-21 04:45:3614274 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1514275 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4114276 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1514277 int rv;
14278 if (round == 0) {
tfarina42834112016-09-22 13:38:2014279 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]044de0642010-06-17 10:42:1514280 } else {
[email protected]49639fa2011-12-20 23:22:4114281 rv = trans.RestartWithAuth(
14282 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1514283 }
14284 if (rv == ERR_IO_PENDING)
14285 rv = callback.WaitForResult();
14286
14287 // Compare results with expected data.
asankae2257db2016-10-11 22:03:1614288 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
[email protected]0b0bf032010-09-21 18:08:5014289 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5514290 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1514291 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
14292 continue;
14293 }
14294 if (round + 1 < test_config.num_auth_rounds) {
Emily Starkf2c9bbd2019-04-09 17:08:5814295 EXPECT_TRUE(response->auth_challenge.has_value());
[email protected]044de0642010-06-17 10:42:1514296 } else {
Emily Starkf2c9bbd2019-04-09 17:08:5814297 EXPECT_FALSE(response->auth_challenge.has_value());
asankae2257db2016-10-11 22:03:1614298 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
[email protected]044de0642010-06-17 10:42:1514299 }
14300 }
[email protected]e5ae96a2010-04-14 20:12:4514301 }
14302}
14303
bncd16676a2016-07-20 16:23:0114304TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1414305 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1414306 HttpAuthHandlerMock::Factory* auth_factory(
14307 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0714308 session_deps_.http_auth_handler_factory.reset(auth_factory);
Bence Béky53a5aef2018-03-29 21:54:1214309 session_deps_.proxy_resolution_service =
14310 ProxyResolutionService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0714311 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
[email protected]c871bce92010-07-15 21:51:1414312
14313 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
14314 auth_handler->set_connection_based(true);
14315 std::string auth_challenge = "Mock realm=server";
14316 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2414317 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
14318 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4914319 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1414320 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
tfarina42834112016-09-22 13:38:2014321 empty_ssl_info, origin, NetLogWithSource());
[email protected]2d01c262011-08-11 23:07:0814322 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1414323
[email protected]c871bce92010-07-15 21:51:1414324 int rv = OK;
Raul Tambre94493c652019-03-11 17:18:3514325 const HttpResponseInfo* response = nullptr;
[email protected]c871bce92010-07-15 21:51:1414326 HttpRequestInfo request;
14327 request.method = "GET";
14328 request.url = origin;
Ramin Halavatib5e433e62018-02-07 07:41:1014329 request.traffic_annotation =
14330 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2714331
danakj1fd259a02016-04-16 03:17:0914332 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1014333
14334 // Use a TCP Socket Pool with only one connection per group. This is used
14335 // to validate that the TCP socket is not released to the pool between
14336 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4214337 HttpNetworkSessionPeer session_peer(session.get());
Matt Menked6fd2a52019-03-20 06:14:3614338 CommonConnectJobParams common_connect_job_params(
14339 session->CreateCommonConnectJobParams());
[email protected]ab739042011-04-07 15:22:2814340 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
Tarun Bansala7635092019-02-20 10:00:5914341 50, // Max sockets for pool
14342 1, // Max sockets per group
14343 base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout
Matt Menkeaafff542019-04-22 22:09:3614344 ProxyServer::Direct(), false, // is_for_websockets
Matt Menked6fd2a52019-03-20 06:14:3614345 &common_connect_job_params, session_deps_.ssl_config_service.get());
Jeremy Roman0579ed62017-08-29 15:56:1914346 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
Matt Menked23ab952019-03-06 00:24:4014347 mock_pool_manager->SetSocketPool(ProxyServer::Direct(),
14348 base::WrapUnique(transport_pool));
dchengc7eeda422015-12-26 03:56:4814349 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1014350
bnc691fda62016-08-12 00:43:1614351 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114352 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1414353
14354 const MockWrite kGet(
14355 "GET / HTTP/1.1\r\n"
14356 "Host: www.example.com\r\n"
14357 "Connection: keep-alive\r\n\r\n");
14358 const MockWrite kGetAuth(
14359 "GET / HTTP/1.1\r\n"
14360 "Host: www.example.com\r\n"
14361 "Connection: keep-alive\r\n"
14362 "Authorization: auth_token\r\n\r\n");
14363
14364 const MockRead kServerChallenge(
14365 "HTTP/1.1 401 Unauthorized\r\n"
14366 "WWW-Authenticate: Mock realm=server\r\n"
14367 "Content-Type: text/html; charset=iso-8859-1\r\n"
14368 "Content-Length: 14\r\n\r\n"
14369 "Unauthorized\r\n");
14370 const MockRead kSuccess(
14371 "HTTP/1.1 200 OK\r\n"
14372 "Content-Type: text/html; charset=iso-8859-1\r\n"
14373 "Content-Length: 3\r\n\r\n"
14374 "Yes");
14375
14376 MockWrite writes[] = {
14377 // First round
14378 kGet,
14379 // Second round
14380 kGetAuth,
14381 // Third round
14382 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3014383 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1014384 kGetAuth,
14385 // Competing request
14386 kGet,
[email protected]c871bce92010-07-15 21:51:1414387 };
14388 MockRead reads[] = {
14389 // First round
14390 kServerChallenge,
14391 // Second round
14392 kServerChallenge,
14393 // Third round
[email protected]eca50e122010-09-11 14:03:3014394 kServerChallenge,
14395 // Fourth round
[email protected]c871bce92010-07-15 21:51:1414396 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1014397 // Competing response
14398 kSuccess,
[email protected]c871bce92010-07-15 21:51:1414399 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114400 StaticSocketDataProvider data_provider(reads, writes);
[email protected]bb88e1d32013-05-03 23:11:0714401 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1414402
Matt Menkef6edce752019-03-19 17:21:5614403 const ClientSocketPool::GroupId kSocketGroup(
14404 HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
Matt Menkebdf777802019-04-22 19:38:5914405 PrivacyMode::PRIVACY_MODE_DISABLED);
[email protected]7ef4cbbb2011-02-06 11:19:1014406
14407 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1414408 auth_handler->SetGenerateExpectation(false, OK);
tfarina42834112016-09-22 13:38:2014409 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]c871bce92010-07-15 21:51:1414410 if (rv == ERR_IO_PENDING)
14411 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114412 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614413 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214414 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814415 EXPECT_TRUE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314416 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114417 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14418 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414419
[email protected]7ef4cbbb2011-02-06 11:19:1014420 // In between rounds, another request comes in for the same domain.
14421 // It should not be able to grab the TCP socket that trans has already
14422 // claimed.
bnc691fda62016-08-12 00:43:1614423 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4114424 TestCompletionCallback callback_compete;
tfarina42834112016-09-22 13:38:2014425 rv = trans_compete.Start(&request, callback_compete.callback(),
14426 NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114427 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1014428 // callback_compete.WaitForResult at this point would stall forever,
14429 // since the HttpNetworkTransaction does not release the request back to
14430 // the pool until after authentication completes.
14431
14432 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1414433 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614434 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414435 if (rv == ERR_IO_PENDING)
14436 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114437 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614438 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214439 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814440 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314441 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114442 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14443 auth_handler->state());
[email protected]c871bce92010-07-15 21:51:1414444
[email protected]7ef4cbbb2011-02-06 11:19:1014445 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1414446 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614447 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1414448 if (rv == ERR_IO_PENDING)
14449 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114450 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614451 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214452 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814453 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314454 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
asanka463ca4262016-11-16 02:34:3114455 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
14456 auth_handler->state());
[email protected]eca50e122010-09-11 14:03:3014457
[email protected]7ef4cbbb2011-02-06 11:19:1014458 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3014459 auth_handler->SetGenerateExpectation(false, OK);
bnc691fda62016-08-12 00:43:1614460 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3014461 if (rv == ERR_IO_PENDING)
14462 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114463 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614464 response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214465 ASSERT_TRUE(response);
Emily Starkf2c9bbd2019-04-09 17:08:5814466 EXPECT_FALSE(response->auth_challenge.has_value());
Raul Tambre8335a6d2019-02-21 16:57:4314467 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014468
asanka463ca4262016-11-16 02:34:3114469 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
14470 // auth handler should transition to a DONE state in concert with the remote
14471 // server. But that's not something we can test here with a mock handler.
14472 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
14473 auth_handler->state());
14474
[email protected]7ef4cbbb2011-02-06 11:19:1014475 // Read the body since the fourth round was successful. This will also
14476 // release the socket back to the pool.
Victor Costan9c7302b2018-08-27 16:39:4414477 scoped_refptr<IOBufferWithSize> io_buf =
14478 base::MakeRefCounted<IOBufferWithSize>(50);
bnc691fda62016-08-12 00:43:1614479 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014480 if (rv == ERR_IO_PENDING)
14481 rv = callback.WaitForResult();
14482 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614483 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014484 EXPECT_EQ(0, rv);
14485 // There are still 0 idle sockets, since the trans_compete transaction
14486 // will be handed it immediately after trans releases it to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314487 EXPECT_EQ(0u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1014488
14489 // The competing request can now finish. Wait for the headers and then
14490 // read the body.
14491 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0114492 EXPECT_THAT(rv, IsOk());
bnc691fda62016-08-12 00:43:1614493 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014494 if (rv == ERR_IO_PENDING)
14495 rv = callback.WaitForResult();
14496 EXPECT_EQ(3, rv);
bnc691fda62016-08-12 00:43:1614497 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1014498 EXPECT_EQ(0, rv);
14499
14500 // Finally, the socket is released to the group.
Raul Tambre8335a6d2019-02-21 16:57:4314501 EXPECT_EQ(1u, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1414502}
14503
[email protected]65041fa2010-05-21 06:56:5314504// This tests the case that a request is issued via http instead of spdy after
14505// npn is negotiated.
bncd16676a2016-07-20 16:23:0114506TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5314507 HttpRequestInfo request;
14508 request.method = "GET";
bncce36dca22015-04-21 22:11:2314509 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014510 request.traffic_annotation =
14511 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]65041fa2010-05-21 06:56:5314512
14513 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314514 MockWrite(
14515 "GET / HTTP/1.1\r\n"
14516 "Host: www.example.org\r\n"
14517 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5314518 };
14519
14520 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5214521 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4314522 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5214523 MockRead("\r\n"),
14524 MockRead("hello world"),
14525 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5314526 };
14527
[email protected]8ddf8322012-02-23 18:08:0614528 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614529 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5314530
[email protected]bb88e1d32013-05-03 23:11:0714531 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5314532
Ryan Sleevib8d7ea02018-05-07 20:01:0114533 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]bb88e1d32013-05-03 23:11:0714534 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5314535
[email protected]49639fa2011-12-20 23:22:4114536 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5314537
danakj1fd259a02016-04-16 03:17:0914538 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614539 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]65041fa2010-05-21 06:56:5314540
tfarina42834112016-09-22 13:38:2014541 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
[email protected]65041fa2010-05-21 06:56:5314542
robpercival214763f2016-07-01 23:27:0114543 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14544 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5314545
bnc691fda62016-08-12 00:43:1614546 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214547 ASSERT_TRUE(response);
14548 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5314549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14550
14551 std::string response_data;
bnc691fda62016-08-12 00:43:1614552 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5314553 EXPECT_EQ("hello world", response_data);
14554
14555 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5214556 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]65041fa2010-05-21 06:56:5314557}
[email protected]26ef6582010-06-24 02:30:4714558
bnc55ff9da2015-08-19 18:42:3514559// Simulate the SSL handshake completing with an NPN negotiation followed by an
14560// immediate server closing of the socket.
14561// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0114562TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4714563 HttpRequestInfo request;
14564 request.method = "GET";
bncce36dca22015-04-21 22:11:2314565 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014566 request.traffic_annotation =
14567 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]26ef6582010-06-24 02:30:4714568
[email protected]8ddf8322012-02-23 18:08:0614569 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3614570 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0714571 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4714572
Ryan Hamilton0239aac2018-05-19 00:03:1314573 spdy::SpdySerializedFrame req(
14574 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114575 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4714576
14577 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614578 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4714579 };
14580
Ryan Sleevib8d7ea02018-05-07 20:01:0114581 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0714582 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4714583
[email protected]49639fa2011-12-20 23:22:4114584 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4714585
danakj1fd259a02016-04-16 03:17:0914586 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1614587 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]26ef6582010-06-24 02:30:4714588
tfarina42834112016-09-22 13:38:2014589 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114590 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14591 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4714592}
[email protected]65d34382010-07-01 18:12:2614593
[email protected]795cbf82013-07-22 09:37:2714594// A subclass of HttpAuthHandlerMock that records the request URL when
14595// it gets it. This is needed since the auth handler may get destroyed
14596// before we get a chance to query it.
14597class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
14598 public:
14599 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
14600
Chris Watkins7a41d3552017-12-01 02:13:2714601 ~UrlRecordingHttpAuthHandlerMock() override = default;
[email protected]795cbf82013-07-22 09:37:2714602
14603 protected:
dchengb03027d2014-10-21 12:00:2014604 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
14605 const HttpRequestInfo* request,
Bence Béky7236fb72018-08-01 14:35:0914606 CompletionOnceCallback callback,
dchengb03027d2014-10-21 12:00:2014607 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2714608 *url_ = request->url;
14609 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
Bence Béky7236fb72018-08-01 14:35:0914610 credentials, request, std::move(callback), auth_token);
[email protected]795cbf82013-07-22 09:37:2714611 }
14612
14613 private:
14614 GURL* url_;
14615};
14616
[email protected]8e6441ca2010-08-19 05:56:3814617// Test that if we cancel the transaction as the connection is completing, that
14618// everything tears down correctly.
bncd16676a2016-07-20 16:23:0114619TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3814620 // Setup everything about the connection to complete synchronously, so that
14621 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
14622 // for is the callback from the HttpStreamRequest.
14623 // Then cancel the transaction.
14624 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3614625 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3814626 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0614627 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
14628 MockRead(SYNCHRONOUS, "hello world"),
14629 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3814630 };
14631
[email protected]8e6441ca2010-08-19 05:56:3814632 HttpRequestInfo request;
14633 request.method = "GET";
bncce36dca22015-04-21 22:11:2314634 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014635 request.traffic_annotation =
14636 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8e6441ca2010-08-19 05:56:3814637
danakj1fd259a02016-04-16 03:17:0914638 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc87dcefc2017-05-25 12:47:5814639 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1914640 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]cb9bf6ca2011-01-28 13:15:2714641
Ryan Sleevib8d7ea02018-05-07 20:01:0114642 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]8e6441ca2010-08-19 05:56:3814643 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0714644 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3814645
[email protected]49639fa2011-12-20 23:22:4114646 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3814647
vishal.b62985ca92015-04-17 08:45:5114648 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4114649 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114650 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3814651 trans.reset(); // Cancel the transaction here.
14652
fdoray92e35a72016-06-10 15:54:5514653 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3014654}
14655
[email protected]ecab6e052014-05-16 14:58:1214656// Test that if a transaction is cancelled after receiving the headers, the
14657// stream is drained properly and added back to the socket pool. The main
14658// purpose of this test is to make sure that an HttpStreamParser can be read
14659// from after the HttpNetworkTransaction and the objects it owns have been
14660// deleted.
14661// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0114662TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1214663 MockRead data_reads[] = {
14664 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
14665 MockRead(ASYNC, "Content-Length: 2\r\n"),
14666 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
14667 MockRead(ASYNC, "1"),
14668 // 2 async reads are necessary to trigger a ReadResponseBody call after the
14669 // HttpNetworkTransaction has been deleted.
14670 MockRead(ASYNC, "2"),
14671 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
14672 };
Ryan Sleevib8d7ea02018-05-07 20:01:0114673 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
[email protected]ecab6e052014-05-16 14:58:1214674 session_deps_.socket_factory->AddSocketDataProvider(&data);
14675
danakj1fd259a02016-04-16 03:17:0914676 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1214677
14678 {
14679 HttpRequestInfo request;
14680 request.method = "GET";
bncce36dca22015-04-21 22:11:2314681 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014682 request.traffic_annotation =
14683 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]ecab6e052014-05-16 14:58:1214684
dcheng48459ac22014-08-26 00:46:4114685 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1214686 TestCompletionCallback callback;
14687
tfarina42834112016-09-22 13:38:2014688 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0114689 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1214690 callback.WaitForResult();
14691
14692 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214693 ASSERT_TRUE(response);
14694 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1214695 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
14696
14697 // The transaction and HttpRequestInfo are deleted.
14698 }
14699
14700 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5514701 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1214702
14703 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4114704 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1214705}
14706
[email protected]76a505b2010-08-25 06:23:0014707// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0114708TEST_F(HttpNetworkTransactionTest, ProxyGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914709 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914710 ProxyResolutionService::CreateFixedFromPacResult(
14711 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114712 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714713 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914714 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014715
[email protected]76a505b2010-08-25 06:23:0014716 HttpRequestInfo request;
14717 request.method = "GET";
bncce36dca22015-04-21 22:11:2314718 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014719 request.traffic_annotation =
14720 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014721
14722 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2314723 MockWrite(
14724 "GET http://www.example.org/ HTTP/1.1\r\n"
14725 "Host: www.example.org\r\n"
14726 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014727 };
14728
14729 MockRead data_reads1[] = {
14730 MockRead("HTTP/1.1 200 OK\r\n"),
14731 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14732 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614733 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014734 };
14735
Ryan Sleevib8d7ea02018-05-07 20:01:0114736 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714737 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0014738
[email protected]49639fa2011-12-20 23:22:4114739 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014740
bnc691fda62016-08-12 00:43:1614741 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914742 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614743 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914744 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14745 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014746
bnc691fda62016-08-12 00:43:1614747 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114748 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014749
14750 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114751 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0014752
bnc691fda62016-08-12 00:43:1614753 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214754 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014755
14756 EXPECT_TRUE(response->headers->IsKeepAlive());
14757 EXPECT_EQ(200, response->headers->response_code());
14758 EXPECT_EQ(100, response->headers->GetContentLength());
14759 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714760 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14761 HostPortPair::FromString("myproxy:70")),
14762 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914763 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14764 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14765 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0014766 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2014767
14768 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614769 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014770 TestLoadTimingNotReusedWithPac(load_timing_info,
14771 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0014772}
14773
14774// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0114775TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
Lily Houghton8c2f97d2018-01-22 05:06:5914776 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914777 ProxyResolutionService::CreateFixedFromPacResult(
14778 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114779 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714780 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914781 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014782
[email protected]76a505b2010-08-25 06:23:0014783 HttpRequestInfo request;
14784 request.method = "GET";
bncce36dca22015-04-21 22:11:2314785 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014786 request.traffic_annotation =
14787 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014788
14789 // Since we have proxy, should try to establish tunnel.
14790 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1714791 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14792 "Host: www.example.org:443\r\n"
14793 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014794
rsleevidb16bb02015-11-12 23:47:1714795 MockWrite("GET / HTTP/1.1\r\n"
14796 "Host: www.example.org\r\n"
14797 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014798 };
14799
14800 MockRead data_reads1[] = {
14801 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14802
14803 MockRead("HTTP/1.1 200 OK\r\n"),
14804 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14805 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614806 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0014807 };
14808
Ryan Sleevib8d7ea02018-05-07 20:01:0114809 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714810 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0614811 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0714812 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0014813
[email protected]49639fa2011-12-20 23:22:4114814 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014815
bnc691fda62016-08-12 00:43:1614816 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
ryansturm49a8cb12016-06-15 16:51:0914817 BeforeHeadersSentHandler headers_handler;
bnc691fda62016-08-12 00:43:1614818 trans.SetBeforeHeadersSentCallback(
ryansturm49a8cb12016-06-15 16:51:0914819 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
14820 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5014821
bnc691fda62016-08-12 00:43:1614822 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114823 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014824
14825 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114826 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5414827 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0014828 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014829 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14830 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014831 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4014832 entries, pos,
mikecirone8b85c432016-09-08 19:11:0014833 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14834 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014835
bnc691fda62016-08-12 00:43:1614836 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214837 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0014838
14839 EXPECT_TRUE(response->headers->IsKeepAlive());
14840 EXPECT_EQ(200, response->headers->response_code());
14841 EXPECT_EQ(100, response->headers->GetContentLength());
14842 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14843 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714844 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14845 HostPortPair::FromString("myproxy:70")),
14846 response->proxy_server);
ryansturm49a8cb12016-06-15 16:51:0914847 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
14848 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
14849 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2014850
14851 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614852 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
[email protected]029c83b62013-01-24 05:28:2014853 TestLoadTimingNotReusedWithPac(load_timing_info,
14854 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0014855}
14856
rsleevidb16bb02015-11-12 23:47:1714857// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
14858// literal host.
bncd16676a2016-07-20 16:23:0114859TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
Lily Houghton8c2f97d2018-01-22 05:06:5914860 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4914861 ProxyResolutionService::CreateFixedFromPacResult(
14862 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714863 BoundTestNetLog log;
14864 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914865 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1714866
14867 HttpRequestInfo request;
14868 request.method = "GET";
Eric Romanda790f92018-11-07 19:17:1514869 request.url = GURL("https://[::2]:443/");
Ramin Halavatib5e433e62018-02-07 07:41:1014870 request.traffic_annotation =
14871 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
rsleevidb16bb02015-11-12 23:47:1714872
14873 // Since we have proxy, should try to establish tunnel.
14874 MockWrite data_writes1[] = {
Eric Romanda790f92018-11-07 19:17:1514875 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
14876 "Host: [::2]:443\r\n"
rsleevidb16bb02015-11-12 23:47:1714877 "Proxy-Connection: keep-alive\r\n\r\n"),
14878
14879 MockWrite("GET / HTTP/1.1\r\n"
Eric Romanda790f92018-11-07 19:17:1514880 "Host: [::2]\r\n"
rsleevidb16bb02015-11-12 23:47:1714881 "Connection: keep-alive\r\n\r\n"),
14882 };
14883
14884 MockRead data_reads1[] = {
14885 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14886
14887 MockRead("HTTP/1.1 200 OK\r\n"),
14888 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14889 MockRead("Content-Length: 100\r\n\r\n"),
14890 MockRead(SYNCHRONOUS, OK),
14891 };
14892
Ryan Sleevib8d7ea02018-05-07 20:01:0114893 StaticSocketDataProvider data1(data_reads1, data_writes1);
rsleevidb16bb02015-11-12 23:47:1714894 session_deps_.socket_factory->AddSocketDataProvider(&data1);
14895 SSLSocketDataProvider ssl(ASYNC, OK);
14896 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14897
14898 TestCompletionCallback callback1;
14899
bnc691fda62016-08-12 00:43:1614900 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
rsleevidb16bb02015-11-12 23:47:1714901
bnc691fda62016-08-12 00:43:1614902 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114903 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1714904
14905 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114906 EXPECT_THAT(rv, IsOk());
Eric Roman79cc7552019-07-19 02:17:5414907 auto entries = log.GetEntries();
rsleevidb16bb02015-11-12 23:47:1714908 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014909 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14910 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1714911 ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014912 entries, pos,
14913 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14914 NetLogEventPhase::NONE);
rsleevidb16bb02015-11-12 23:47:1714915
bnc691fda62016-08-12 00:43:1614916 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5214917 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1714918
14919 EXPECT_TRUE(response->headers->IsKeepAlive());
14920 EXPECT_EQ(200, response->headers->response_code());
14921 EXPECT_EQ(100, response->headers->GetContentLength());
14922 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14923 EXPECT_TRUE(response->was_fetched_via_proxy);
tbansal2ecbbc72016-10-06 17:15:4714924 EXPECT_EQ(ProxyServer(ProxyServer::SCHEME_HTTP,
14925 HostPortPair::FromString("myproxy:70")),
14926 response->proxy_server);
rsleevidb16bb02015-11-12 23:47:1714927
14928 LoadTimingInfo load_timing_info;
bnc691fda62016-08-12 00:43:1614929 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
rsleevidb16bb02015-11-12 23:47:1714930 TestLoadTimingNotReusedWithPac(load_timing_info,
14931 CONNECT_TIMING_HAS_SSL_TIMES);
14932}
14933
[email protected]76a505b2010-08-25 06:23:0014934// Test a basic HTTPS GET request through a proxy, but the server hangs up
14935// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0114936TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
Ramin Halavatica8d5252018-03-12 05:33:4914937 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
14938 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5114939 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0714940 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0914941 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0014942
[email protected]76a505b2010-08-25 06:23:0014943 HttpRequestInfo request;
14944 request.method = "GET";
bncce36dca22015-04-21 22:11:2314945 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1014946 request.traffic_annotation =
14947 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]76a505b2010-08-25 06:23:0014948
14949 // Since we have proxy, should try to establish tunnel.
14950 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1714951 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14952 "Host: www.example.org:443\r\n"
14953 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014954
rsleevidb16bb02015-11-12 23:47:1714955 MockWrite("GET / HTTP/1.1\r\n"
14956 "Host: www.example.org\r\n"
14957 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0014958 };
14959
14960 MockRead data_reads1[] = {
[email protected]76a505b2010-08-25 06:23:0014961 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0614962 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0014963 };
14964
Ryan Sleevib8d7ea02018-05-07 20:01:0114965 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]bb88e1d32013-05-03 23:11:0714966 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0614967 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0714968 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0014969
[email protected]49639fa2011-12-20 23:22:4114970 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0014971
bnc691fda62016-08-12 00:43:1614972 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]0b0bf032010-09-21 18:08:5014973
bnc691fda62016-08-12 00:43:1614974 int rv = trans.Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0114975 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0014976
14977 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0114978 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
Eric Roman79cc7552019-07-19 02:17:5414979 auto entries = log.GetEntries();
[email protected]76a505b2010-08-25 06:23:0014980 size_t pos = ExpectLogContainsSomewhere(
mikecirone8b85c432016-09-08 19:11:0014981 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14982 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014983 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4014984 entries, pos,
mikecirone8b85c432016-09-08 19:11:0014985 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14986 NetLogEventPhase::NONE);
[email protected]76a505b2010-08-25 06:23:0014987}
14988
[email protected]749eefa82010-09-13 22:14:0314989// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0114990TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
Ryan Hamilton0239aac2018-05-19 00:03:1314991 spdy::SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4914992 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4114993 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0314994
Raul Tambre94493c652019-03-11 17:18:3514995 spdy::SpdySerializedFrame resp(
14996 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1314997 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0314998 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4114999 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0315000 };
15001
Ryan Sleevib8d7ea02018-05-07 20:01:0115002 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715003 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0315004
[email protected]8ddf8322012-02-23 18:08:0615005 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3615006 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0715007 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0315008
danakj1fd259a02016-04-16 03:17:0915009 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0315010
15011 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2315012 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4015013 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
Matt Menke2436b2f2018-12-11 18:07:1115014 PRIVACY_MODE_DISABLED,
15015 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]795cbf82013-07-22 09:37:2715016 base::WeakPtr<SpdySession> spdy_session =
Bence Béky0ef1556e2017-06-30 19:52:5215017 CreateSpdySession(session.get(), key, NetLogWithSource());
[email protected]749eefa82010-09-13 22:14:0315018
15019 HttpRequestInfo request;
15020 request.method = "GET";
bncce36dca22015-04-21 22:11:2315021 request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1015022 request.traffic_annotation =
15023 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]749eefa82010-09-13 22:14:0315024
bnc691fda62016-08-12 00:43:1615025 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]749eefa82010-09-13 22:14:0315026
[email protected]41d64e82013-07-03 22:44:2615027 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015028 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115029 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15030 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0315031}
15032
[email protected]73b8dd222010-11-11 19:55:2415033// Given a net error, cause that error to be returned from the first Write()
bnc691fda62016-08-12 00:43:1615034// call and verify that the HttpNetworkTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0215035void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0715036 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2915037 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715038 request_info.url = GURL("https://www.example.com/");
15039 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915040 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015041 request_info.traffic_annotation =
15042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715043
[email protected]8ddf8322012-02-23 18:08:0615044 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2915045 MockWrite data_writes[] = {
15046 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2415047 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115048 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
[email protected]bb88e1d32013-05-03 23:11:0715049 session_deps_.socket_factory->AddSocketDataProvider(&data);
15050 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2415051
danakj1fd259a02016-04-16 03:17:0915052 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615053 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]73b8dd222010-11-11 19:55:2415054
[email protected]49639fa2011-12-20 23:22:4115055 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015056 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
ttuttle859dc7a2015-04-23 19:42:2915057 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2415058 rv = callback.WaitForResult();
15059 ASSERT_EQ(error, rv);
15060}
15061
bncd16676a2016-07-20 16:23:0115062TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2415063 // Just check a grab bag of cert errors.
15064 static const int kErrors[] = {
15065 ERR_CERT_COMMON_NAME_INVALID,
15066 ERR_CERT_AUTHORITY_INVALID,
15067 ERR_CERT_DATE_INVALID,
15068 };
Avi Drissman4365a4782018-12-28 19:26:2415069 for (size_t i = 0; i < base::size(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0615070 CheckErrorIsPassedBack(kErrors[i], ASYNC);
15071 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2415072 }
15073}
15074
[email protected]bd0b6772011-01-11 19:59:3015075// Ensure that a client certificate is removed from the SSL client auth
15076// cache when:
15077// 1) No proxy is involved.
15078// 2) TLS False Start is disabled.
15079// 3) The initial TLS handshake requests a client certificate.
15080// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115081TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915082 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715083 request_info.url = GURL("https://www.example.com/");
15084 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915085 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015086 request_info.traffic_annotation =
15087 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715088
David Benjamin1c4b6d012019-07-08 17:12:5715089 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115090 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015091
15092 // [ssl_]data1 contains the data for the first SSL handshake. When a
15093 // CertificateRequest is received for the first time, the handshake will
15094 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2915095 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015096 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715097 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115098 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715099 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015100
15101 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
15102 // False Start is not being used, the result of the SSL handshake will be
15103 // returned as part of the SSLClientSocket::Connect() call. This test
15104 // matches the result of a server sending a handshake_failure alert,
15105 // rather than a Finished message, because it requires a client
15106 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2915107 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3015108 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715109 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
Ryan Sleevib8d7ea02018-05-07 20:01:0115110 StaticSocketDataProvider data2;
[email protected]bb88e1d32013-05-03 23:11:0715111 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015112
15113 // [ssl_]data3 contains the data for the third SSL handshake. When a
15114 // connection to a server fails during an SSL handshake,
Steven Valdez0ef94d02018-11-19 23:28:1315115 // HttpNetworkTransaction will attempt to fallback to TLSv1.2 if the previous
15116 // connection was attempted with TLSv1.3. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3015117 // of the HttpNetworkTransaction. Because this test failure is due to
15118 // requiring a client certificate, this fallback handshake should also
15119 // fail.
ttuttle859dc7a2015-04-23 19:42:2915120 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
Steven Valdez0ef94d02018-11-19 23:28:1315121 ssl_data3.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
[email protected]bd0b6772011-01-11 19:59:3015122 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715123 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115124 StaticSocketDataProvider data3;
[email protected]bb88e1d32013-05-03 23:11:0715125 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015126
[email protected]80c75f682012-05-26 16:22:1715127 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
15128 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4215129 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
15130 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1715131 // of the HttpNetworkTransaction. Because this test failure is due to
15132 // requiring a client certificate, this fallback handshake should also
15133 // fail.
ttuttle859dc7a2015-04-23 19:42:2915134 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1715135 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715136 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115137 StaticSocketDataProvider data4;
[email protected]bb88e1d32013-05-03 23:11:0715138 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715139
danakj1fd259a02016-04-16 03:17:0915140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615141 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015142
[email protected]bd0b6772011-01-11 19:59:3015143 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4115144 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015145 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115146 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015147
15148 // Complete the SSL handshake, which should abort due to requiring a
15149 // client certificate.
15150 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115151 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015152
15153 // Indicate that no certificate should be supplied. From the perspective
15154 // of SSLClientCertCache, NULL is just as meaningful as a real
15155 // certificate, so this is the same as supply a
15156 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515157 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115158 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015159
15160 // Ensure the certificate was added to the client auth cache before
15161 // allowing the connection to continue restarting.
15162 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415163 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4115164 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415165 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215166 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015167
15168 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715169 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15170 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015171 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115172 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015173
15174 // Ensure that the client certificate is removed from the cache on a
15175 // handshake failure.
[email protected]791879c2013-12-17 07:22:4115176 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415177 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015178}
15179
15180// Ensure that a client certificate is removed from the SSL client auth
15181// cache when:
15182// 1) No proxy is involved.
15183// 2) TLS False Start is enabled.
15184// 3) The initial TLS handshake requests a client certificate.
15185// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0115186TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2915187 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2715188 request_info.url = GURL("https://www.example.com/");
15189 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915190 request_info.load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015191 request_info.traffic_annotation =
15192 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]cb9bf6ca2011-01-28 13:15:2715193
David Benjamin1c4b6d012019-07-08 17:12:5715194 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115195 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3015196
15197 // When TLS False Start is used, SSLClientSocket::Connect() calls will
15198 // return successfully after reading up to the peer's Certificate message.
15199 // This is to allow the caller to call SSLClientSocket::Write(), which can
15200 // enqueue application data to be sent in the same packet as the
15201 // ChangeCipherSpec and Finished messages.
15202 // The actual handshake will be finished when SSLClientSocket::Read() is
15203 // called, which expects to process the peer's ChangeCipherSpec and
15204 // Finished messages. If there was an error negotiating with the peer,
15205 // such as due to the peer requiring a client certificate when none was
15206 // supplied, the alert sent by the peer won't be processed until Read() is
15207 // called.
15208
15209 // Like the non-False Start case, when a client certificate is requested by
15210 // the peer, the handshake is aborted during the Connect() call.
15211 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2915212 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3015213 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715214 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
Ryan Sleevib8d7ea02018-05-07 20:01:0115215 StaticSocketDataProvider data1;
[email protected]bb88e1d32013-05-03 23:11:0715216 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3015217
15218 // When a client certificate is supplied, Connect() will not be aborted
15219 // when the peer requests the certificate. Instead, the handshake will
15220 // artificially succeed, allowing the caller to write the HTTP request to
15221 // the socket. The handshake messages are not processed until Read() is
15222 // called, which then detects that the handshake was aborted, due to the
15223 // peer sending a handshake_failure because it requires a client
15224 // certificate.
ttuttle859dc7a2015-04-23 19:42:2915225 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015226 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715227 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2915228 MockRead data2_reads[] = {
15229 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3015230 };
Ryan Sleevib8d7ea02018-05-07 20:01:0115231 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715232 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3015233
15234 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1715235 // the data for the SSL handshake once the TLSv1.1 connection falls back to
15236 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915237 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3015238 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715239 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
Ryan Sleevib8d7ea02018-05-07 20:01:0115240 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715241 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3015242
[email protected]80c75f682012-05-26 16:22:1715243 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
15244 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2915245 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1715246 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0715247 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
Ryan Sleevib8d7ea02018-05-07 20:01:0115248 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
[email protected]bb88e1d32013-05-03 23:11:0715249 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1715250
[email protected]7799de12013-05-30 05:52:5115251 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2915252 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5115253 ssl_data5.cert_request_info = cert_request.get();
15254 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
Ryan Sleevib8d7ea02018-05-07 20:01:0115255 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
[email protected]7799de12013-05-30 05:52:5115256 session_deps_.socket_factory->AddSocketDataProvider(&data5);
15257
danakj1fd259a02016-04-16 03:17:0915258 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1615259 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]bd0b6772011-01-11 19:59:3015260
[email protected]bd0b6772011-01-11 19:59:3015261 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4115262 TestCompletionCallback callback;
tfarina42834112016-09-22 13:38:2015263 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115264 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015265
15266 // Complete the SSL handshake, which should abort due to requiring a
15267 // client certificate.
15268 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115269 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3015270
15271 // Indicate that no certificate should be supplied. From the perspective
15272 // of SSLClientCertCache, NULL is just as meaningful as a real
15273 // certificate, so this is the same as supply a
15274 // legitimate-but-unacceptable certificate.
Raul Tambre94493c652019-03-11 17:18:3515275 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
robpercival214763f2016-07-01 23:27:0115276 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3015277
15278 // Ensure the certificate was added to the client auth cache before
15279 // allowing the connection to continue restarting.
15280 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5415281 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4115282 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415283 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5215284 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3015285
[email protected]bd0b6772011-01-11 19:59:3015286 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1715287 // then consume ssl_data3 and ssl_data4, both of which should also fail.
15288 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3015289 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115290 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3015291
15292 // Ensure that the client certificate is removed from the cache on a
15293 // handshake failure.
[email protected]791879c2013-12-17 07:22:4115294 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5415295 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3015296}
15297
[email protected]8c405132011-01-11 22:03:1815298// Ensure that a client certificate is removed from the SSL client auth
15299// cache when:
15300// 1) An HTTPS proxy is involved.
15301// 3) The HTTPS proxy requests a client certificate.
15302// 4) The client supplies an invalid/unacceptable certificate for the
15303// proxy.
bncd16676a2016-07-20 16:23:0115304TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
Ramin Halavatica8d5252018-03-12 05:33:4915305 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
15306 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5115307 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0715308 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1815309
David Benjamin3b94b0f2019-04-25 23:07:5215310 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
[email protected]791879c2013-12-17 07:22:4115311 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1815312
David Benjamin3b94b0f2019-04-25 23:07:5215313 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
15314 // an HTTP endpoint.
ttuttle859dc7a2015-04-23 19:42:2915315 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1815316 requests[0].url = GURL("https://www.example.com/");
15317 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915318 requests[0].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015319 requests[0].traffic_annotation =
15320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815321
David Benjamin3b94b0f2019-04-25 23:07:5215322 // HTTPS requests are tunneled.
15323 MockWrite https_writes[] = {
15324 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
15325 "Host: www.example.com:443\r\n"
15326 "Proxy-Connection: keep-alive\r\n\r\n"),
15327 };
15328
[email protected]8c405132011-01-11 22:03:1815329 requests[1].url = GURL("http://www.example.com/");
15330 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2915331 requests[1].load_flags = LOAD_NORMAL;
Ramin Halavatib5e433e62018-02-07 07:41:1015332 requests[1].traffic_annotation =
15333 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]8c405132011-01-11 22:03:1815334
David Benjamin3b94b0f2019-04-25 23:07:5215335 // HTTP requests are not.
15336 MockWrite http_writes[] = {
15337 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
15338 "Host: www.example.com\r\n"
15339 "Proxy-Connection: keep-alive\r\n\r\n"),
15340 };
[email protected]8c405132011-01-11 22:03:1815341
David Benjamin3b94b0f2019-04-25 23:07:5215342 // When the server rejects the client certificate, it will close the
15343 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
15344 // TLS 1.2 with False Start), the error is returned out of the first Read().
15345 for (bool reject_in_connect : {true, false}) {
15346 SCOPED_TRACE(reject_in_connect);
15347 // Client certificate errors are typically signaled with
15348 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
15349 // protocol error.
15350 for (Error reject_error :
15351 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
15352 SCOPED_TRACE(reject_error);
15353 // Tunneled and non-tunneled requests are handled differently. Test both.
15354 for (const HttpRequestInfo& request : requests) {
15355 SCOPED_TRACE(request.url);
[email protected]8c405132011-01-11 22:03:1815356
David Benjamin3b94b0f2019-04-25 23:07:5215357 session_deps_.socket_factory =
15358 std::make_unique<MockClientSocketFactory>();
[email protected]8c405132011-01-11 22:03:1815359
David Benjamin3b94b0f2019-04-25 23:07:5215360 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
15361 // [ssl_]data[1-2]. [ssl_]data3 is not needed because we do not retry
15362 // for proxies. Rather than represending the endpoint
15363 // (www.example.com:443), they represent failures with the HTTPS proxy
15364 // (proxy:70).
15365 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
15366 ssl_data1.cert_request_info = cert_request.get();
15367 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15368 StaticSocketDataProvider data1;
15369 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1815370
David Benjamin3b94b0f2019-04-25 23:07:5215371 base::Optional<SSLSocketDataProvider> ssl_data2;
15372 base::Optional<StaticSocketDataProvider> data2;
15373 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
15374 if (reject_in_connect) {
15375 ssl_data2.emplace(ASYNC, reject_error);
15376 // There are no reads or writes.
15377 data2.emplace();
15378 } else {
15379 ssl_data2.emplace(ASYNC, OK);
15380 // We will get one Write() in before observing the error in Read().
15381 if (request.url.SchemeIsCryptographic()) {
15382 data2.emplace(error_in_read, https_writes);
15383 } else {
15384 data2.emplace(error_in_read, http_writes);
15385 }
15386 }
15387 ssl_data2->cert_request_info = cert_request.get();
[email protected]8c405132011-01-11 22:03:1815388
David Benjamin3b94b0f2019-04-25 23:07:5215389 session_deps_.socket_factory->AddSSLSocketDataProvider(
15390 &ssl_data2.value());
15391 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
[email protected]8c405132011-01-11 22:03:1815392
David Benjamin3b94b0f2019-04-25 23:07:5215393 std::unique_ptr<HttpNetworkSession> session =
15394 CreateSession(&session_deps_);
15395 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15396
15397 // Begin the SSL handshake with the proxy.
15398 TestCompletionCallback callback;
15399 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15400 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15401
15402 // Complete the SSL handshake, which should abort due to requiring a
15403 // client certificate.
15404 rv = callback.WaitForResult();
15405 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15406
15407 // Indicate that no certificate should be supplied. From the
15408 // perspective of SSLClientCertCache, NULL is just as meaningful as a
15409 // real certificate, so this is the same as supply a
15410 // legitimate-but-unacceptable certificate.
15411 rv =
15412 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
15413 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15414
15415 // Ensure the certificate was added to the client auth cache before
15416 // allowing the connection to continue restarting.
15417 scoped_refptr<X509Certificate> client_cert;
15418 scoped_refptr<SSLPrivateKey> client_private_key;
15419 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
15420 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15421 ASSERT_FALSE(client_cert);
15422 // Ensure the certificate was NOT cached for the endpoint. This only
15423 // applies to HTTPS requests, but is fine to check for HTTP requests.
15424 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15425 HostPortPair("www.example.com", 443), &client_cert,
15426 &client_private_key));
15427
15428 // Restart the handshake. This will consume ssl_data2. The result code
15429 // is checked against what ssl_data2 should return.
15430 rv = callback.WaitForResult();
15431 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
15432 IsError(reject_error)));
15433
15434 // Now that the new handshake has failed, ensure that the client
15435 // certificate was removed from the client auth cache.
15436 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15437 HostPortPair("proxy", 70), &client_cert, &client_private_key));
15438 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
15439 HostPortPair("www.example.com", 443), &client_cert,
15440 &client_private_key));
15441 }
15442 }
[email protected]8c405132011-01-11 22:03:1815443 }
15444}
15445
David Benjamin1a0566082019-04-30 07:36:1915446// Test that HttpNetworkTransaction correctly handles (mocked) certificate
15447// requests during a TLS renegotiation.
15448TEST_F(HttpNetworkTransactionTest, CertificateRequestInRenego) {
15449 HttpRequestInfo request_info;
15450 request_info.url = GURL("https://www.example.com/");
15451 request_info.method = "GET";
15452 request_info.load_flags = LOAD_NORMAL;
15453 request_info.traffic_annotation =
15454 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15455
15456 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
15457 cert_request->host_and_port = HostPortPair("www.example.com", 443);
15458
15459 std::unique_ptr<FakeClientCertIdentity> identity =
15460 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
15461 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
15462 ASSERT_TRUE(identity);
15463
15464 // The first connection's handshake succeeds, but we get
15465 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
15466 SSLSocketDataProvider ssl_data1(ASYNC, OK);
15467 ssl_data1.cert_request_info = cert_request.get();
15468 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
15469 MockWrite data1_writes[] = {
15470 MockWrite("GET / HTTP/1.1\r\n"
15471 "Host: www.example.com\r\n"
15472 "Connection: keep-alive\r\n\r\n"),
15473 };
15474 MockRead data1_reads[] = {
15475 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
15476 };
15477 StaticSocketDataProvider data1(data1_reads, data1_writes);
15478 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15479
15480 // After supplying with certificate, we restart the request from the top,
15481 // which succeeds this time.
15482 SSLSocketDataProvider ssl_data2(ASYNC, OK);
15483 ssl_data2.expected_send_client_cert = true;
15484 ssl_data2.expected_client_cert = identity->certificate();
15485 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
15486 MockWrite data2_writes[] = {
15487 MockWrite("GET / HTTP/1.1\r\n"
15488 "Host: www.example.com\r\n"
15489 "Connection: keep-alive\r\n\r\n"),
15490 };
15491 MockRead data2_reads[] = {
15492 MockRead("HTTP/1.1 200 OK\r\n"
15493 "Content-Length: 0\r\n\r\n"),
15494 };
15495 StaticSocketDataProvider data2(data2_reads, data2_writes);
15496 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15497
15498 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
15499 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15500
15501 TestCompletionCallback callback;
15502 int rv = callback.GetResult(
15503 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
15504 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
15505
15506 rv = trans.RestartWithCertificate(identity->certificate(),
15507 identity->ssl_private_key(),
15508 callback.callback());
15509 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
15510
15511 // Ensure the certificate was added to the client auth cache
15512 // allowing the connection to continue restarting.
15513 scoped_refptr<X509Certificate> client_cert;
15514 scoped_refptr<SSLPrivateKey> client_private_key;
15515 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
15516 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15517 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15518
15519 // Complete the handshake. The request now succeeds.
15520 rv = callback.WaitForResult();
15521 ASSERT_THAT(rv, IsError(OK));
15522 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
15523
15524 // The client certificate remains in the cache.
15525 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
15526 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
15527 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
15528}
15529
bncd16676a2016-07-20 16:23:0115530TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4615531 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915532 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915533 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615534
bnc032658ba2016-09-26 18:17:1515535 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615536
Ryan Hamilton0239aac2018-05-19 00:03:1315537 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915538 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815539 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315540 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715541 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615542 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115543 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615544 };
Ryan Hamilton0239aac2018-05-19 00:03:1315545 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515546 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315547 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115548 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315549 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515550 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315551 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115552 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615553 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115554 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15555 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315556 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615557 };
15558
eroman36d84e54432016-03-17 03:23:0215559 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215560 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115561 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715562 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615563
[email protected]aa22b242011-11-16 18:58:2915564 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615565 HttpRequestInfo request1;
15566 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315567 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615568 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015569 request1.traffic_annotation =
15570 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015571 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615572
tfarina42834112016-09-22 13:38:2015573 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115574 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15575 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615576
15577 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215578 ASSERT_TRUE(response);
15579 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215580 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615581
15582 std::string response_data;
robpercival214763f2016-07-01 23:27:0115583 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615584 EXPECT_EQ("hello!", response_data);
15585
bnca4d611d2016-09-22 19:55:3715586 // Preload mail.example.com into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315587 rv = session_deps_.host_resolver->LoadIntoCache(
15588 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0115589 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4615590
15591 HttpRequestInfo request2;
15592 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715593 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4615594 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015595 request2.traffic_annotation =
15596 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015597 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615598
tfarina42834112016-09-22 13:38:2015599 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115600 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15601 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615602
15603 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215604 ASSERT_TRUE(response);
15605 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215606 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615607 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215608 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115609 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615610 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4615611}
15612
bncd16676a2016-07-20 16:23:0115613TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0215614 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
Jeremy Roman0579ed62017-08-29 15:56:1915615 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
danakj1fd259a02016-04-16 03:17:0915616 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0215617
bnc032658ba2016-09-26 18:17:1515618 AddSSLSocketData();
[email protected]d2b5f092012-06-08 23:55:0215619
Ryan Hamilton0239aac2018-05-19 00:03:1315620 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915621 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815622 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315623 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715624 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0215625 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115626 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0215627 };
Ryan Hamilton0239aac2018-05-19 00:03:1315628 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515629 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315630 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115631 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315632 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515633 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315634 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115635 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0215636 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115637 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15638 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315639 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0215640 };
15641
eroman36d84e54432016-03-17 03:23:0215642 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215643 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115644 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715645 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0215646
15647 TestCompletionCallback callback;
15648 HttpRequestInfo request1;
15649 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315650 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0215651 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015652 request1.traffic_annotation =
15653 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015654 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215655
tfarina42834112016-09-22 13:38:2015656 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115657 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15658 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215659
15660 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215661 ASSERT_TRUE(response);
15662 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215663 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215664
15665 std::string response_data;
robpercival214763f2016-07-01 23:27:0115666 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215667 EXPECT_EQ("hello!", response_data);
15668
15669 HttpRequestInfo request2;
15670 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3715671 request2.url = GURL("https://mail.example.com/");
[email protected]d2b5f092012-06-08 23:55:0215672 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015673 request2.traffic_annotation =
15674 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015675 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0215676
tfarina42834112016-09-22 13:38:2015677 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115678 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15679 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215680
15681 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5215682 ASSERT_TRUE(response);
15683 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215684 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0215685 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5215686 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0115687 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0215688 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0215689}
15690
bnc8016c1f2017-03-31 02:11:2915691// Regression test for https://crbug.com/546991.
15692// The server might not be able to serve an IP pooled request, and might send a
15693// 421 Misdirected Request response status to indicate this.
15694// HttpNetworkTransaction should reset the request and retry without IP pooling.
15695TEST_F(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
15696 // Two hosts resolve to the same IP address.
15697 const std::string ip_addr = "1.2.3.4";
15698 IPAddress ip;
15699 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15700 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15701
Jeremy Roman0579ed62017-08-29 15:56:1915702 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bnc8016c1f2017-03-31 02:11:2915703 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15704 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15705
15706 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15707
15708 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315709 spdy::SpdySerializedFrame req1(
bnc8016c1f2017-03-31 02:11:2915710 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15711 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315712 spdy::SpdySerializedFrame req2(
bnc8016c1f2017-03-31 02:11:2915713 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315714 spdy::SpdySerializedFrame rst(
15715 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
bnc8016c1f2017-03-31 02:11:2915716 MockWrite writes1[] = {
15717 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15718 CreateMockWrite(rst, 6),
15719 };
15720
15721 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315722 spdy::SpdySerializedFrame resp1(
15723 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15724 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15725 spdy::SpdyHeaderBlock response_headers;
15726 response_headers[spdy::kHttp2StatusHeader] = "421";
15727 spdy::SpdySerializedFrame resp2(
bnc8016c1f2017-03-31 02:11:2915728 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
15729 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15730 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15731
15732 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115733 SequencedSocketData data1(connect1, reads1, writes1);
bnc8016c1f2017-03-31 02:11:2915734 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15735
15736 AddSSLSocketData();
15737
15738 // Retry the second request on a second connection.
15739 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315740 spdy::SpdySerializedFrame req3(
bnc8016c1f2017-03-31 02:11:2915741 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15742 MockWrite writes2[] = {
15743 CreateMockWrite(req3, 0),
15744 };
15745
Ryan Hamilton0239aac2018-05-19 00:03:1315746 spdy::SpdySerializedFrame resp3(
15747 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
15748 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
bnc8016c1f2017-03-31 02:11:2915749 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15750 MockRead(ASYNC, 0, 3)};
15751
15752 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115753 SequencedSocketData data2(connect2, reads2, writes2);
bnc8016c1f2017-03-31 02:11:2915754 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15755
15756 AddSSLSocketData();
15757
15758 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315759 int rv = session_deps_.host_resolver->LoadIntoCache(
15760 HostPortPair("mail.example.com", 443), base::nullopt);
bnc8016c1f2017-03-31 02:11:2915761 EXPECT_THAT(rv, IsOk());
15762
15763 HttpRequestInfo request1;
15764 request1.method = "GET";
15765 request1.url = GURL("https://www.example.org/");
15766 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015767 request1.traffic_annotation =
15768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915769 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15770
Eric Orthf4db66a2019-02-19 21:35:3315771 TestCompletionCallback callback;
bnc8016c1f2017-03-31 02:11:2915772 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15773 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15774 rv = callback.WaitForResult();
15775 EXPECT_THAT(rv, IsOk());
15776
15777 const HttpResponseInfo* response = trans1.GetResponseInfo();
15778 ASSERT_TRUE(response);
15779 ASSERT_TRUE(response->headers);
15780 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15781 EXPECT_TRUE(response->was_fetched_via_spdy);
15782 EXPECT_TRUE(response->was_alpn_negotiated);
15783 std::string response_data;
15784 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
15785 EXPECT_EQ("hello!", response_data);
15786
15787 HttpRequestInfo request2;
15788 request2.method = "GET";
15789 request2.url = GURL("https://mail.example.org/");
15790 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015791 request2.traffic_annotation =
15792 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc8016c1f2017-03-31 02:11:2915793 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
15794
15795 BoundTestNetLog log;
15796 rv = trans2.Start(&request2, callback.callback(), log.bound());
15797 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15798 rv = callback.WaitForResult();
15799 EXPECT_THAT(rv, IsOk());
15800
15801 response = trans2.GetResponseInfo();
15802 ASSERT_TRUE(response);
15803 ASSERT_TRUE(response->headers);
15804 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15805 EXPECT_TRUE(response->was_fetched_via_spdy);
15806 EXPECT_TRUE(response->was_alpn_negotiated);
15807 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
15808 EXPECT_EQ("hello!", response_data);
15809
Eric Roman79cc7552019-07-19 02:17:5415810 auto entries = log.GetEntries();
davidbence688ae2017-05-04 15:12:5915811 ExpectLogContainsSomewhere(
15812 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
bnc8016c1f2017-03-31 02:11:2915813 NetLogEventPhase::NONE);
davidbence688ae2017-05-04 15:12:5915814}
15815
15816// Test that HTTP 421 responses are properly returned to the caller if received
15817// on the retry as well. HttpNetworkTransaction should not infinite loop or lose
15818// portions of the response.
15819TEST_F(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
15820 // Two hosts resolve to the same IP address.
15821 const std::string ip_addr = "1.2.3.4";
15822 IPAddress ip;
15823 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
15824 IPEndPoint peer_addr = IPEndPoint(ip, 443);
15825
Jeremy Roman0579ed62017-08-29 15:56:1915826 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
davidbence688ae2017-05-04 15:12:5915827 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
15828 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
15829
15830 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15831
15832 // Two requests on the first connection.
Ryan Hamilton0239aac2018-05-19 00:03:1315833 spdy::SpdySerializedFrame req1(
davidbence688ae2017-05-04 15:12:5915834 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
15835 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315836 spdy::SpdySerializedFrame req2(
davidbence688ae2017-05-04 15:12:5915837 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1315838 spdy::SpdySerializedFrame rst(
15839 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
davidbence688ae2017-05-04 15:12:5915840 MockWrite writes1[] = {
15841 CreateMockWrite(req1, 0), CreateMockWrite(req2, 3),
15842 CreateMockWrite(rst, 6),
15843 };
15844
15845 // The first one succeeds, the second gets error 421 Misdirected Request.
Ryan Hamilton0239aac2018-05-19 00:03:1315846 spdy::SpdySerializedFrame resp1(
15847 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
15848 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
15849 spdy::SpdyHeaderBlock response_headers;
15850 response_headers[spdy::kHttp2StatusHeader] = "421";
15851 spdy::SpdySerializedFrame resp2(
davidbence688ae2017-05-04 15:12:5915852 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
15853 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
15854 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
15855
15856 MockConnect connect1(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115857 SequencedSocketData data1(connect1, reads1, writes1);
davidbence688ae2017-05-04 15:12:5915858 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15859
15860 AddSSLSocketData();
15861
15862 // Retry the second request on a second connection. It returns 421 Misdirected
15863 // Retry again.
15864 SpdyTestUtil spdy_util2;
Ryan Hamilton0239aac2018-05-19 00:03:1315865 spdy::SpdySerializedFrame req3(
davidbence688ae2017-05-04 15:12:5915866 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
15867 MockWrite writes2[] = {
15868 CreateMockWrite(req3, 0),
15869 };
15870
Ryan Hamilton0239aac2018-05-19 00:03:1315871 spdy::SpdySerializedFrame resp3(
davidbence688ae2017-05-04 15:12:5915872 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
Ryan Hamilton0239aac2018-05-19 00:03:1315873 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
davidbence688ae2017-05-04 15:12:5915874 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
15875 MockRead(ASYNC, 0, 3)};
15876
15877 MockConnect connect2(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115878 SequencedSocketData data2(connect2, reads2, writes2);
davidbence688ae2017-05-04 15:12:5915879 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15880
15881 AddSSLSocketData();
15882
15883 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315884 int rv = session_deps_.host_resolver->LoadIntoCache(
15885 HostPortPair("mail.example.com", 443), base::nullopt);
davidbence688ae2017-05-04 15:12:5915886 EXPECT_THAT(rv, IsOk());
15887
15888 HttpRequestInfo request1;
15889 request1.method = "GET";
15890 request1.url = GURL("https://www.example.org/");
15891 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015892 request1.traffic_annotation =
15893 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5915894 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
15895
Eric Orthf4db66a2019-02-19 21:35:3315896 TestCompletionCallback callback;
davidbence688ae2017-05-04 15:12:5915897 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
15898 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15899 rv = callback.WaitForResult();
15900 EXPECT_THAT(rv, IsOk());
15901
15902 const HttpResponseInfo* response = trans1.GetResponseInfo();
15903 ASSERT_TRUE(response);
15904 ASSERT_TRUE(response->headers);
15905 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
15906 EXPECT_TRUE(response->was_fetched_via_spdy);
15907 EXPECT_TRUE(response->was_alpn_negotiated);
15908 std::string response_data;
15909 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
15910 EXPECT_EQ("hello!", response_data);
15911
15912 HttpRequestInfo request2;
15913 request2.method = "GET";
15914 request2.url = GURL("https://mail.example.org/");
15915 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015916 request2.traffic_annotation =
15917 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
davidbence688ae2017-05-04 15:12:5915918 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
15919
15920 BoundTestNetLog log;
15921 rv = trans2.Start(&request2, callback.callback(), log.bound());
15922 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15923 rv = callback.WaitForResult();
15924 EXPECT_THAT(rv, IsOk());
15925
15926 // After a retry, the 421 Misdirected Request is reported back up to the
15927 // caller.
15928 response = trans2.GetResponseInfo();
15929 ASSERT_TRUE(response);
15930 ASSERT_TRUE(response->headers);
15931 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
15932 EXPECT_TRUE(response->was_fetched_via_spdy);
15933 EXPECT_TRUE(response->was_alpn_negotiated);
15934 EXPECT_TRUE(response->ssl_info.cert);
15935 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
15936 EXPECT_EQ("hello!", response_data);
bnc8016c1f2017-03-31 02:11:2915937}
15938
bncd16676a2016-07-20 16:23:0115939TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1315940 UseIPConnectionPoolingWithHostCacheExpiration) {
Eric Orth1da75de2019-02-20 21:10:3415941 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
15942 session_deps_.host_resolver =
15943 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
danakj1fd259a02016-04-16 03:17:0915944 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]e3ceb682011-06-28 23:55:4615945
bnc032658ba2016-09-26 18:17:1515946 AddSSLSocketData();
[email protected]e3ceb682011-06-28 23:55:4615947
Ryan Hamilton0239aac2018-05-19 00:03:1315948 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4915949 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3815950 spdy_util_.UpdateWithStreamDestruction(1);
Ryan Hamilton0239aac2018-05-19 00:03:1315951 spdy::SpdySerializedFrame host2_req(
bnca4d611d2016-09-22 19:55:3715952 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4615953 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4115954 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4615955 };
Ryan Hamilton0239aac2018-05-19 00:03:1315956 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3515957 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1315958 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4115959 spdy_util_.ConstructSpdyDataFrame(1, true));
Ryan Hamilton0239aac2018-05-19 00:03:1315960 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3515961 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1315962 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4115963 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4615964 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4115965 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
15966 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1315967 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4615968 };
15969
eroman36d84e54432016-03-17 03:23:0215970 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0215971 MockConnect connect(ASYNC, OK, peer_addr);
Ryan Sleevib8d7ea02018-05-07 20:01:0115972 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
[email protected]bb88e1d32013-05-03 23:11:0715973 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4615974
[email protected]aa22b242011-11-16 18:58:2915975 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4615976 HttpRequestInfo request1;
15977 request1.method = "GET";
bncce36dca22015-04-21 22:11:2315978 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4615979 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1015980 request1.traffic_annotation =
15981 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5015982 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4615983
tfarina42834112016-09-22 13:38:2015984 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0115985 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15986 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615987
15988 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5215989 ASSERT_TRUE(response);
15990 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0215991 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4615992
15993 std::string response_data;
robpercival214763f2016-07-01 23:27:0115994 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4615995 EXPECT_EQ("hello!", response_data);
15996
15997 // Preload cache entries into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3315998 rv = session_deps_.host_resolver->LoadIntoCache(
15999 HostPortPair("mail.example.com", 443), base::nullopt);
robpercival214763f2016-07-01 23:27:0116000 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4616001
16002 HttpRequestInfo request2;
16003 request2.method = "GET";
bnca4d611d2016-09-22 19:55:3716004 request2.url = GURL("https://mail.example.com/");
[email protected]e3ceb682011-06-28 23:55:4616005 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016006 request2.traffic_annotation =
16007 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016008 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4616009
tfarina42834112016-09-22 13:38:2016010 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116011 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16012 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616013
16014 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216015 ASSERT_TRUE(response);
16016 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216017 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4616018 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216019 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116020 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4616021 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4616022}
16023
bncd16676a2016-07-20 16:23:0116024TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2316025 const std::string https_url = "https://www.example.org:8080/";
16026 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416027
16028 // SPDY GET for HTTPS URL
Ryan Hamilton0239aac2018-05-19 00:03:1316029 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916030 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0416031
16032 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116033 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0416034 };
16035
Raul Tambre94493c652019-03-11 17:18:3516036 spdy::SpdySerializedFrame resp1(
16037 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316038 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116039 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5916040 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0416041
Ryan Sleevib8d7ea02018-05-07 20:01:0116042 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416043 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716044 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416045
16046 // HTTP GET for the HTTP URL
16047 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1316048 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3416049 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2316050 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3416051 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0416052 };
16053
16054 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1316055 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
16056 MockRead(ASYNC, 2, "hello"),
16057 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0416058 };
16059
Ryan Sleevib8d7ea02018-05-07 20:01:0116060 SequencedSocketData data2(reads2, writes2);
[email protected]8450d722012-07-02 19:14:0416061
[email protected]8450d722012-07-02 19:14:0416062 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616063 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0716064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16065 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16066 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0416067
danakj1fd259a02016-04-16 03:17:0916068 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0416069
16070 // Start the first transaction to set up the SpdySession
16071 HttpRequestInfo request1;
16072 request1.method = "GET";
16073 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416074 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016075 request1.traffic_annotation =
16076 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016077 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416078 TestCompletionCallback callback1;
16079 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016080 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516081 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416082
robpercival214763f2016-07-01 23:27:0116083 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416084 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16085
16086 // Now, start the HTTP request
16087 HttpRequestInfo request2;
16088 request2.method = "GET";
16089 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416090 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016091 request2.traffic_annotation =
16092 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016093 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416094 TestCompletionCallback callback2;
16095 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016096 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516097 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0416098
robpercival214763f2016-07-01 23:27:0116099 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0416100 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16101}
16102
bnc5452e2a2015-05-08 16:27:4216103// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
16104// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0116105TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2516106 url::SchemeHostPort server("https", "www.example.org", 443);
16107 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4216108
bnc8bef8da22016-05-30 01:28:2516109 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4216110 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616111 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216112 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16113
16114 // No data should be read from the alternative, because HTTP/1.1 is
16115 // negotiated.
16116 StaticSocketDataProvider data;
16117 session_deps_.socket_factory->AddSocketDataProvider(&data);
16118
16119 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4616120 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4216121 // mocked. This way the request relies on the alternate Job.
16122 StaticSocketDataProvider data_refused;
16123 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16124 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16125
zhongyi3d4a55e72016-04-22 20:36:4616126 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916127 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016128 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216129 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116130 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216131 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116132 http_server_properties->SetHttp2AlternativeService(
16133 server, alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216134
bnc5452e2a2015-05-08 16:27:4216135 HttpRequestInfo request;
krasinc06a72a2016-12-21 03:42:4616136 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216137 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2516138 request.url = GURL("https://www.example.org:443");
Ramin Halavatib5e433e62018-02-07 07:41:1016139 request.traffic_annotation =
16140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216141 TestCompletionCallback callback;
16142
16143 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
bnc94c92842016-09-21 15:22:5216144 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
tfarina42834112016-09-22 13:38:2016145 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
bnc94c92842016-09-21 15:22:5216146 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4216147}
16148
bnc40448a532015-05-11 19:13:1416149// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4616150// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1416151// succeeds, the request should succeed, even if the latter fails because
16152// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0116153TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2516154 url::SchemeHostPort server("https", "www.example.org", 443);
16155 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1416156
16157 // Negotiate HTTP/1.1 with alternative.
16158 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616159 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416160 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
16161
16162 // No data should be read from the alternative, because HTTP/1.1 is
16163 // negotiated.
16164 StaticSocketDataProvider data;
16165 session_deps_.socket_factory->AddSocketDataProvider(&data);
16166
zhongyi3d4a55e72016-04-22 20:36:4616167 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1416168 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616169 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1416170 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
16171
16172 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2516173 MockWrite("GET / HTTP/1.1\r\n"
16174 "Host: www.example.org\r\n"
16175 "Connection: keep-alive\r\n\r\n"),
16176 MockWrite("GET /second HTTP/1.1\r\n"
16177 "Host: www.example.org\r\n"
16178 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1416179 };
16180
16181 MockRead http_reads[] = {
16182 MockRead("HTTP/1.1 200 OK\r\n"),
16183 MockRead("Content-Type: text/html\r\n"),
16184 MockRead("Content-Length: 6\r\n\r\n"),
16185 MockRead("foobar"),
16186 MockRead("HTTP/1.1 200 OK\r\n"),
16187 MockRead("Content-Type: text/html\r\n"),
16188 MockRead("Content-Length: 7\r\n\r\n"),
16189 MockRead("another"),
16190 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116191 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc40448a532015-05-11 19:13:1416192 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16193
zhongyi3d4a55e72016-04-22 20:36:4616194 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916195 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016196 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1416197 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116198 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216199 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116200 http_server_properties->SetHttp2AlternativeService(
16201 server, alternative_service, expiration);
bnc40448a532015-05-11 19:13:1416202
16203 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
16204 HttpRequestInfo request1;
16205 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2516206 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1416207 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016208 request1.traffic_annotation =
16209 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416210 TestCompletionCallback callback1;
16211
tfarina42834112016-09-22 13:38:2016212 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416213 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116214 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416215
16216 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5216217 ASSERT_TRUE(response1);
16218 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1416219 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
16220
16221 std::string response_data1;
robpercival214763f2016-07-01 23:27:0116222 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1416223 EXPECT_EQ("foobar", response_data1);
16224
16225 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
16226 // for alternative service.
16227 EXPECT_TRUE(
16228 http_server_properties->IsAlternativeServiceBroken(alternative_service));
16229
zhongyi3d4a55e72016-04-22 20:36:4616230 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1416231 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4616232 // to server.
bnc40448a532015-05-11 19:13:1416233 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
16234 HttpRequestInfo request2;
16235 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2516236 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1416237 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016238 request2.traffic_annotation =
16239 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc40448a532015-05-11 19:13:1416240 TestCompletionCallback callback2;
16241
tfarina42834112016-09-22 13:38:2016242 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
bnc40448a532015-05-11 19:13:1416243 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0116244 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1416245
16246 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5216247 ASSERT_TRUE(response2);
16248 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1416249 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
16250
16251 std::string response_data2;
robpercival214763f2016-07-01 23:27:0116252 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1416253 EXPECT_EQ("another", response_data2);
16254}
16255
bnc5452e2a2015-05-08 16:27:4216256// Alternative service requires HTTP/2 (or SPDY), but there is already a
16257// HTTP/1.1 socket open to the alternative server. That socket should not be
16258// used.
bncd16676a2016-07-20 16:23:0116259TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4616260 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4216261 HostPortPair alternative("alternative.example.org", 443);
16262 std::string origin_url = "https://origin.example.org:443";
16263 std::string alternative_url = "https://alternative.example.org:443";
16264
16265 // Negotiate HTTP/1.1 with alternative.example.org.
16266 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616267 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4216268 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16269
16270 // HTTP/1.1 data for |request1| and |request2|.
16271 MockWrite http_writes[] = {
16272 MockWrite(
16273 "GET / HTTP/1.1\r\n"
16274 "Host: alternative.example.org\r\n"
16275 "Connection: keep-alive\r\n\r\n"),
16276 MockWrite(
16277 "GET / HTTP/1.1\r\n"
16278 "Host: alternative.example.org\r\n"
16279 "Connection: keep-alive\r\n\r\n"),
16280 };
16281
16282 MockRead http_reads[] = {
16283 MockRead(
16284 "HTTP/1.1 200 OK\r\n"
16285 "Content-Type: text/html; charset=iso-8859-1\r\n"
16286 "Content-Length: 40\r\n\r\n"
16287 "first HTTP/1.1 response from alternative"),
16288 MockRead(
16289 "HTTP/1.1 200 OK\r\n"
16290 "Content-Type: text/html; charset=iso-8859-1\r\n"
16291 "Content-Length: 41\r\n\r\n"
16292 "second HTTP/1.1 response from alternative"),
16293 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116294 StaticSocketDataProvider http_data(http_reads, http_writes);
bnc5452e2a2015-05-08 16:27:4216295 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16296
16297 // This test documents that an alternate Job should not pool to an already
16298 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4616299 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4216300 StaticSocketDataProvider data_refused;
16301 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16302 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16303
zhongyi3d4a55e72016-04-22 20:36:4616304 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0916305 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4016306 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4216307 session->http_server_properties();
bnc3472afd2016-11-17 15:27:2116308 AlternativeService alternative_service(kProtoHTTP2, alternative);
bnc7dc7e1b42015-07-28 14:43:1216309 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyie537a002017-06-27 16:48:2116310 http_server_properties->SetHttp2AlternativeService(
16311 server, alternative_service, expiration);
bnc5452e2a2015-05-08 16:27:4216312
16313 // First transaction to alternative to open an HTTP/1.1 socket.
bnc5452e2a2015-05-08 16:27:4216314 HttpRequestInfo request1;
krasinc06a72a2016-12-21 03:42:4616315 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216316 request1.method = "GET";
16317 request1.url = GURL(alternative_url);
16318 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016319 request1.traffic_annotation =
16320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216321 TestCompletionCallback callback1;
16322
tfarina42834112016-09-22 13:38:2016323 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116324 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616325 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216326 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5216327 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4216328 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216329 EXPECT_TRUE(response1->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216330 EXPECT_FALSE(response1->was_fetched_via_spdy);
16331 std::string response_data1;
bnc691fda62016-08-12 00:43:1616332 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4216333 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
16334
16335 // Request for origin.example.org, which has an alternative service. This
16336 // will start two Jobs: the alternative looks for connections to pool to,
16337 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4616338 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4216339 // this request fails.
bnc5452e2a2015-05-08 16:27:4216340 HttpRequestInfo request2;
krasinc06a72a2016-12-21 03:42:4616341 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216342 request2.method = "GET";
16343 request2.url = GURL(origin_url);
16344 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016345 request2.traffic_annotation =
16346 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216347 TestCompletionCallback callback2;
16348
tfarina42834112016-09-22 13:38:2016349 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116350 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4216351
16352 // Another transaction to alternative. This is to test that the HTTP/1.1
16353 // socket is still open and in the pool.
bnc5452e2a2015-05-08 16:27:4216354 HttpRequestInfo request3;
krasinc06a72a2016-12-21 03:42:4616355 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
bnc5452e2a2015-05-08 16:27:4216356 request3.method = "GET";
16357 request3.url = GURL(alternative_url);
16358 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016359 request3.traffic_annotation =
16360 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc5452e2a2015-05-08 16:27:4216361 TestCompletionCallback callback3;
16362
tfarina42834112016-09-22 13:38:2016363 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116364 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc691fda62016-08-12 00:43:1616365 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
bnc5452e2a2015-05-08 16:27:4216366 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5216367 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4216368 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
bnc94c92842016-09-21 15:22:5216369 EXPECT_TRUE(response3->was_alpn_negotiated);
bnc5452e2a2015-05-08 16:27:4216370 EXPECT_FALSE(response3->was_fetched_via_spdy);
16371 std::string response_data3;
bnc691fda62016-08-12 00:43:1616372 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4216373 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
16374}
16375
bncd16676a2016-07-20 16:23:0116376TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2316377 const std::string https_url = "https://www.example.org:8080/";
16378 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0416379
rdsmithebb50aa2015-11-12 03:44:3816380 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0116381 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3816382
[email protected]8450d722012-07-02 19:14:0416383 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2316384 const HostPortPair host_port_pair("www.example.org", 8080);
Matt Menke6e879bd2019-03-18 17:26:0416385 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
16386 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
16387 host_port_pair));
Ryan Hamilton0239aac2018-05-19 00:03:1316388 spdy::SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4916389 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
Ryan Hamilton0239aac2018-05-19 00:03:1316390 spdy::SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0216391 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3916392
16393 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
Ryan Hamilton0239aac2018-05-19 00:03:1316394 spdy::SpdyHeaderBlock req2_block;
16395 req2_block[spdy::kHttp2MethodHeader] = "GET";
16396 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
16397 req2_block[spdy::kHttp2SchemeHeader] = "http";
16398 req2_block[spdy::kHttp2PathHeader] = "/";
16399 spdy::SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1516400 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0416401
16402 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116403 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
16404 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0416405 };
16406
Ryan Hamilton0239aac2018-05-19 00:03:1316407 spdy::SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1516408 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316409 spdy::SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1516410 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316411 spdy::SpdySerializedFrame body1(
16412 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
16413 spdy::SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3816414 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316415 spdy::SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3816416 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
Raul Tambre94493c652019-03-11 17:18:3516417 spdy::SpdySerializedFrame resp2(
16418 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
Ryan Hamilton0239aac2018-05-19 00:03:1316419 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3316420 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116421 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3316422 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4116423 CreateMockRead(wrapped_resp1, 4),
16424 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3316425 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4116426 CreateMockRead(resp2, 8),
16427 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3316428 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
16429 };
[email protected]8450d722012-07-02 19:14:0416430
Ryan Sleevib8d7ea02018-05-07 20:01:0116431 SequencedSocketData data1(reads1, writes1);
[email protected]8450d722012-07-02 19:14:0416432 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5716433 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0416434
Lily Houghton8c2f97d2018-01-22 05:06:5916435 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4916436 ProxyResolutionService::CreateFixedFromPacResult(
16437 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
vishal.b62985ca92015-04-17 08:45:5116438 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0716439 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0416440 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616441 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316442 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0416443 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616444 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16446 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0416447
danakj1fd259a02016-04-16 03:17:0916448 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0416449
16450 // Start the first transaction to set up the SpdySession
16451 HttpRequestInfo request1;
16452 request1.method = "GET";
16453 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0416454 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016455 request1.traffic_annotation =
16456 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016457 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0416458 TestCompletionCallback callback1;
tfarina42834112016-09-22 13:38:2016459 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416460
mmenke666a6fea2015-12-19 04:16:3316461 // This pause is a hack to avoid running into https://crbug.com/497228.
16462 data1.RunUntilPaused();
16463 base::RunLoop().RunUntilIdle();
16464 data1.Resume();
robpercival214763f2016-07-01 23:27:0116465 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0416466 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16467
[email protected]f6c63db52013-02-02 00:35:2216468 LoadTimingInfo load_timing_info1;
16469 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
16470 TestLoadTimingNotReusedWithPac(load_timing_info1,
16471 CONNECT_TIMING_HAS_SSL_TIMES);
16472
mmenke666a6fea2015-12-19 04:16:3316473 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0416474 HttpRequestInfo request2;
16475 request2.method = "GET";
16476 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0416477 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016478 request2.traffic_annotation =
16479 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016480 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0416481 TestCompletionCallback callback2;
tfarina42834112016-09-22 13:38:2016482 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
[email protected]8450d722012-07-02 19:14:0416483
mmenke666a6fea2015-12-19 04:16:3316484 // This pause is a hack to avoid running into https://crbug.com/497228.
16485 data1.RunUntilPaused();
16486 base::RunLoop().RunUntilIdle();
16487 data1.Resume();
robpercival214763f2016-07-01 23:27:0116488 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3316489
[email protected]8450d722012-07-02 19:14:0416490 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2216491
16492 LoadTimingInfo load_timing_info2;
16493 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
16494 // The established SPDY sessions is considered reused by the HTTP request.
16495 TestLoadTimingReusedWithPac(load_timing_info2);
16496 // HTTP requests over a SPDY session should have a different connection
16497 // socket_log_id than requests over a tunnel.
16498 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0416499}
16500
[email protected]2d88e7d2012-07-19 17:55:1716501// Test that in the case where we have a SPDY session to a SPDY proxy
16502// that we do not pool other origins that resolve to the same IP when
16503// the certificate does not match the new origin.
16504// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0116505TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2316506 const std::string url1 = "http://www.example.org/";
16507 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1716508 const std::string ip_addr = "1.2.3.4";
16509
rdsmithebb50aa2015-11-12 03:44:3816510 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0116511 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3816512
[email protected]2d88e7d2012-07-19 17:55:1716513 // SPDY GET for HTTP URL (through SPDY proxy)
Ryan Hamilton0239aac2018-05-19 00:03:1316514 spdy::SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2316515 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
Ryan Hamilton0239aac2018-05-19 00:03:1316516 spdy::SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1516517 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1716518
16519 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4116520 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1716521 };
16522
Raul Tambre94493c652019-03-11 17:18:3516523 spdy::SpdySerializedFrame resp1(
16524 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316525 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1716526 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4116527 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
16528 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1716529 };
16530
Ryan Sleevib8d7ea02018-05-07 20:01:0116531 SequencedSocketData data1(reads1, writes1);
martijnfe9636e2016-02-06 14:33:3216532 IPAddress ip;
martijn654c8c42016-02-10 22:10:5916533 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1716534 IPEndPoint peer_addr = IPEndPoint(ip, 443);
16535 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3316536 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1716537
16538 // SPDY GET for HTTPS URL (direct)
Ryan Hamilton0239aac2018-05-19 00:03:1316539 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916540 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1716541
16542 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116543 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1716544 };
16545
Ryan Hamilton0239aac2018-05-19 00:03:1316546 spdy::SpdySerializedFrame resp2(
Raul Tambre94493c652019-03-11 17:18:3516547 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316548 spdy::SpdySerializedFrame body2(
16549 spdy_util_secure.ConstructSpdyDataFrame(1, true));
bncdf80d44fd2016-07-15 20:27:4116550 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3316551 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1716552
Ryan Sleevib8d7ea02018-05-07 20:01:0116553 SequencedSocketData data2(reads2, writes2);
[email protected]2d88e7d2012-07-19 17:55:1716554 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3316555 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1716556
16557 // Set up a proxy config that sends HTTP requests to a proxy, and
16558 // all others direct.
16559 ProxyConfig proxy_config;
16560 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
Ramin Halavatica8d5252018-03-12 05:33:4916561 session_deps_.proxy_resolution_service =
16562 std::make_unique<ProxyResolutionService>(
16563 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
16564 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
16565 nullptr, nullptr);
[email protected]2d88e7d2012-07-19 17:55:1716566
bncce36dca22015-04-21 22:11:2316567 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3616568 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1716569 // Load a valid cert. Note, that this does not need to
16570 // be valid for proxy because the MockSSLClientSocket does
16571 // not actually verify it. But SpdySession will use this
16572 // to see if it is valid for the new origin
Ryan Sleevi4f832092017-11-21 23:25:4916573 ssl1.ssl_info.cert =
16574 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
16575 ASSERT_TRUE(ssl1.ssl_info.cert);
mmenke666a6fea2015-12-19 04:16:3316576 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16577 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1716578
16579 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3616580 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3316581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16582 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1716583
Jeremy Roman0579ed62017-08-29 15:56:1916584 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
bncce36dca22015-04-21 22:11:2316585 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0716586 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1716587
danakj1fd259a02016-04-16 03:17:0916588 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1716589
16590 // Start the first transaction to set up the SpdySession
16591 HttpRequestInfo request1;
16592 request1.method = "GET";
16593 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1716594 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016595 request1.traffic_annotation =
16596 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016597 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716598 TestCompletionCallback callback1;
16599 ASSERT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016600 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
mmenke666a6fea2015-12-19 04:16:3316601 // This pause is a hack to avoid running into https://crbug.com/497228.
16602 data1.RunUntilPaused();
16603 base::RunLoop().RunUntilIdle();
16604 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1716605
robpercival214763f2016-07-01 23:27:0116606 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716607 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
16608
16609 // Now, start the HTTP request
16610 HttpRequestInfo request2;
16611 request2.method = "GET";
16612 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1716613 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016614 request2.traffic_annotation =
16615 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016616 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1716617 TestCompletionCallback callback2;
16618 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016619 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
fdoray92e35a72016-06-10 15:54:5516620 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1716621
16622 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0116623 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1716624 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16625}
16626
[email protected]85f97342013-04-17 06:12:2416627// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
16628// error) in SPDY session, removes the socket from pool and closes the SPDY
16629// session. Verify that new url's from the same HttpNetworkSession (and a new
16630// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0116631TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2316632 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2416633
16634 MockRead reads1[] = {
16635 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
16636 };
16637
Ryan Sleevib8d7ea02018-05-07 20:01:0116638 SequencedSocketData data1(reads1, base::span<MockWrite>());
[email protected]85f97342013-04-17 06:12:2416639
Ryan Hamilton0239aac2018-05-19 00:03:1316640 spdy::SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4916641 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2416642 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4116643 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2416644 };
16645
Raul Tambre94493c652019-03-11 17:18:3516646 spdy::SpdySerializedFrame resp2(
16647 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316648 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2416649 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4116650 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
16651 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2416652 };
16653
Ryan Sleevib8d7ea02018-05-07 20:01:0116654 SequencedSocketData data2(reads2, writes2);
[email protected]85f97342013-04-17 06:12:2416655
[email protected]85f97342013-04-17 06:12:2416656 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616657 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016658 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16659 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2416660
16661 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616662 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5016663 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16664 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2416665
danakj1fd259a02016-04-16 03:17:0916666 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5016667 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2416668
16669 // Start the first transaction to set up the SpdySession and verify that
16670 // connection was closed.
16671 HttpRequestInfo request1;
16672 request1.method = "GET";
16673 request1.url = GURL(https_url);
16674 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016675 request1.traffic_annotation =
16676 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016677 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416678 TestCompletionCallback callback1;
16679 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016680 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0116681 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2416682
16683 // Now, start the second request and make sure it succeeds.
16684 HttpRequestInfo request2;
16685 request2.method = "GET";
16686 request2.url = GURL(https_url);
16687 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016688 request2.traffic_annotation =
16689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]90499482013-06-01 00:39:5016690 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2416691 TestCompletionCallback callback2;
16692 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2016693 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
[email protected]85f97342013-04-17 06:12:2416694
robpercival214763f2016-07-01 23:27:0116695 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2416696 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
16697}
16698
bncd16676a2016-07-20 16:23:0116699TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0316700 ClientSocketPoolManager::set_max_sockets_per_group(
16701 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16702 ClientSocketPoolManager::set_max_sockets_per_pool(
16703 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
16704
16705 // Use two different hosts with different IPs so they don't get pooled.
16706 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
16707 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0916708 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0316709
16710 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616711 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316712 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3616713 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0316714 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
16715 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
16716
Ryan Hamilton0239aac2018-05-19 00:03:1316717 spdy::SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4916718 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316719 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116720 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0316721 };
Ryan Hamilton0239aac2018-05-19 00:03:1316722 spdy::SpdySerializedFrame host1_resp(
Raul Tambre94493c652019-03-11 17:18:3516723 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316724 spdy::SpdySerializedFrame host1_resp_body(
bncdf80d44fd2016-07-15 20:27:4116725 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316726 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116727 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916728 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316729 };
16730
rdsmithebb50aa2015-11-12 03:44:3816731 // Use a separate test instance for the separate SpdySession that will be
16732 // created.
bncd16676a2016-07-20 16:23:0116733 SpdyTestUtil spdy_util_2;
Ryan Sleevib8d7ea02018-05-07 20:01:0116734 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
Bence Béky53a5aef2018-03-29 21:54:1216735 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
[email protected]483fa202013-05-14 01:07:0316736
Ryan Hamilton0239aac2018-05-19 00:03:1316737 spdy::SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4916738 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0316739 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4116740 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0316741 };
Ryan Hamilton0239aac2018-05-19 00:03:1316742 spdy::SpdySerializedFrame host2_resp(
Raul Tambre94493c652019-03-11 17:18:3516743 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
Ryan Hamilton0239aac2018-05-19 00:03:1316744 spdy::SpdySerializedFrame host2_resp_body(
bncdf80d44fd2016-07-15 20:27:4116745 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0316746 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4116747 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5916748 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0316749 };
16750
Ryan Sleevib8d7ea02018-05-07 20:01:0116751 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
Bence Béky53a5aef2018-03-29 21:54:1216752 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
[email protected]483fa202013-05-14 01:07:0316753
16754 MockWrite http_write[] = {
16755 MockWrite("GET / HTTP/1.1\r\n"
16756 "Host: www.a.com\r\n"
16757 "Connection: keep-alive\r\n\r\n"),
16758 };
16759
16760 MockRead http_read[] = {
16761 MockRead("HTTP/1.1 200 OK\r\n"),
16762 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
16763 MockRead("Content-Length: 6\r\n\r\n"),
16764 MockRead("hello!"),
16765 };
Ryan Sleevib8d7ea02018-05-07 20:01:0116766 StaticSocketDataProvider http_data(http_read, http_write);
[email protected]483fa202013-05-14 01:07:0316767 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16768
16769 HostPortPair host_port_pair_a("www.a.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116770 SpdySessionKey spdy_session_key_a(
16771 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16772 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[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_a));
[email protected]483fa202013-05-14 01:07:0316775
16776 TestCompletionCallback callback;
16777 HttpRequestInfo request1;
16778 request1.method = "GET";
16779 request1.url = GURL("https://www.a.com/");
16780 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016781 request1.traffic_annotation =
16782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816783 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1916784 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316785
tfarina42834112016-09-22 13:38:2016786 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116787 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16788 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316789
16790 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216791 ASSERT_TRUE(response);
16792 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216793 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316794 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216795 EXPECT_TRUE(response->was_alpn_negotiated);
[email protected]483fa202013-05-14 01:07:0316796
16797 std::string response_data;
robpercival214763f2016-07-01 23:27:0116798 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316799 EXPECT_EQ("hello!", response_data);
16800 trans.reset();
16801 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616802 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316803
16804 HostPortPair host_port_pair_b("www.b.com", 443);
Matt Menke2436b2f2018-12-11 18:07:1116805 SpdySessionKey spdy_session_key_b(
16806 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16807 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316808 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616809 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316810 HttpRequestInfo request2;
16811 request2.method = "GET";
16812 request2.url = GURL("https://www.b.com/");
16813 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016814 request2.traffic_annotation =
16815 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816816 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916817 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316818
tfarina42834112016-09-22 13:38:2016819 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116820 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16821 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316822
16823 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216824 ASSERT_TRUE(response);
16825 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0216826 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0316827 EXPECT_TRUE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216828 EXPECT_TRUE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116829 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316830 EXPECT_EQ("hello!", response_data);
16831 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616832 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316833 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2616834 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316835
16836 HostPortPair host_port_pair_a1("www.a.com", 80);
Matt Menke2436b2f2018-12-11 18:07:1116837 SpdySessionKey spdy_session_key_a1(
16838 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
16839 SpdySessionKey::IsProxySession::kFalse, SocketTag());
[email protected]483fa202013-05-14 01:07:0316840 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616841 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0316842 HttpRequestInfo request3;
16843 request3.method = "GET";
16844 request3.url = GURL("http://www.a.com/");
16845 request3.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1016846 request3.traffic_annotation =
16847 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
bnc87dcefc2017-05-25 12:47:5816848 trans =
Jeremy Roman0579ed62017-08-29 15:56:1916849 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
[email protected]483fa202013-05-14 01:07:0316850
tfarina42834112016-09-22 13:38:2016851 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116852 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16853 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0316854
16855 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5216856 ASSERT_TRUE(response);
16857 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0316858 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16859 EXPECT_FALSE(response->was_fetched_via_spdy);
bnc94c92842016-09-21 15:22:5216860 EXPECT_FALSE(response->was_alpn_negotiated);
robpercival214763f2016-07-01 23:27:0116861 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0316862 EXPECT_EQ("hello!", response_data);
16863 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616864 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0316865 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2616866 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0316867}
16868
bncd16676a2016-07-20 16:23:0116869TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0416870 HttpRequestInfo request;
16871 request.method = "GET";
bncce36dca22015-04-21 22:11:2316872 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016873 request.traffic_annotation =
16874 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416875
danakj1fd259a02016-04-16 03:17:0916876 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616877 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416878
ttuttled9dbc652015-09-29 20:00:5916879 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0416880 StaticSocketDataProvider data;
16881 data.set_connect_data(mock_connect);
16882 session_deps_.socket_factory->AddSocketDataProvider(&data);
16883
16884 TestCompletionCallback callback;
16885
tfarina42834112016-09-22 13:38:2016886 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116887 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416888
16889 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116890 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0416891
[email protected]79e1fd62013-06-20 06:50:0416892 // We don't care whether this succeeds or fails, but it shouldn't crash.
16893 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616894 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4716895
16896 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1616897 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4716898 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0116899 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5916900
16901 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1616902 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5916903 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0416904}
16905
bncd16676a2016-07-20 16:23:0116906TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0416907 HttpRequestInfo request;
16908 request.method = "GET";
bncce36dca22015-04-21 22:11:2316909 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016910 request.traffic_annotation =
16911 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416912
danakj1fd259a02016-04-16 03:17:0916913 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616914 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416915
ttuttled9dbc652015-09-29 20:00:5916916 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0416917 StaticSocketDataProvider data;
16918 data.set_connect_data(mock_connect);
16919 session_deps_.socket_factory->AddSocketDataProvider(&data);
16920
16921 TestCompletionCallback callback;
16922
tfarina42834112016-09-22 13:38:2016923 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116924 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416925
16926 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116927 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0416928
[email protected]79e1fd62013-06-20 06:50:0416929 // We don't care whether this succeeds or fails, but it shouldn't crash.
16930 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616931 trans.GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4716932
16933 ConnectionAttempts attempts;
bnc691fda62016-08-12 00:43:1616934 trans.GetConnectionAttempts(&attempts);
ttuttle1f2d7e92015-04-28 16:17:4716935 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0116936 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5916937
16938 IPEndPoint endpoint;
bnc691fda62016-08-12 00:43:1616939 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
ttuttled9dbc652015-09-29 20:00:5916940 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0416941}
16942
bncd16676a2016-07-20 16:23:0116943TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0416944 HttpRequestInfo request;
16945 request.method = "GET";
bncce36dca22015-04-21 22:11:2316946 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016947 request.traffic_annotation =
16948 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416949
danakj1fd259a02016-04-16 03:17:0916950 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616951 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416952
16953 MockWrite data_writes[] = {
16954 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
16955 };
16956 MockRead data_reads[] = {
16957 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
16958 };
16959
Ryan Sleevib8d7ea02018-05-07 20:01:0116960 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0416961 session_deps_.socket_factory->AddSocketDataProvider(&data);
16962
16963 TestCompletionCallback callback;
16964
tfarina42834112016-09-22 13:38:2016965 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116966 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0416967
16968 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0116969 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0416970
[email protected]79e1fd62013-06-20 06:50:0416971 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1616972 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0416973 EXPECT_TRUE(request_headers.HasHeader("Host"));
16974}
16975
bncd16676a2016-07-20 16:23:0116976TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0416977 HttpRequestInfo request;
16978 request.method = "GET";
bncce36dca22015-04-21 22:11:2316979 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1016980 request.traffic_annotation =
16981 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0416982
danakj1fd259a02016-04-16 03:17:0916983 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1616984 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0416985
16986 MockWrite data_writes[] = {
16987 MockWrite(ASYNC, ERR_CONNECTION_RESET),
16988 };
16989 MockRead data_reads[] = {
16990 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
16991 };
16992
Ryan Sleevib8d7ea02018-05-07 20:01:0116993 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0416994 session_deps_.socket_factory->AddSocketDataProvider(&data);
16995
16996 TestCompletionCallback callback;
16997
tfarina42834112016-09-22 13:38:2016998 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0116999 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417000
17001 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117002 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417003
[email protected]79e1fd62013-06-20 06:50:0417004 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617005 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417006 EXPECT_TRUE(request_headers.HasHeader("Host"));
17007}
17008
bncd16676a2016-07-20 16:23:0117009TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417010 HttpRequestInfo request;
17011 request.method = "GET";
bncce36dca22015-04-21 22:11:2317012 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017013 request.traffic_annotation =
17014 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417015
danakj1fd259a02016-04-16 03:17:0917016 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617017 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417018
17019 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317020 MockWrite(
17021 "GET / HTTP/1.1\r\n"
17022 "Host: www.example.org\r\n"
17023 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417024 };
17025 MockRead data_reads[] = {
17026 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
17027 };
17028
Ryan Sleevib8d7ea02018-05-07 20:01:0117029 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417030 session_deps_.socket_factory->AddSocketDataProvider(&data);
17031
17032 TestCompletionCallback callback;
17033
tfarina42834112016-09-22 13:38:2017034 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117035 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417036
17037 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117038 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417039
[email protected]79e1fd62013-06-20 06:50:0417040 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617041 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417042 EXPECT_TRUE(request_headers.HasHeader("Host"));
17043}
17044
bncd16676a2016-07-20 16:23:0117045TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0417046 HttpRequestInfo request;
17047 request.method = "GET";
bncce36dca22015-04-21 22:11:2317048 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017049 request.traffic_annotation =
17050 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417051
danakj1fd259a02016-04-16 03:17:0917052 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617053 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417054
17055 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317056 MockWrite(
17057 "GET / HTTP/1.1\r\n"
17058 "Host: www.example.org\r\n"
17059 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417060 };
17061 MockRead data_reads[] = {
17062 MockRead(ASYNC, ERR_CONNECTION_RESET),
17063 };
17064
Ryan Sleevib8d7ea02018-05-07 20:01:0117065 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417066 session_deps_.socket_factory->AddSocketDataProvider(&data);
17067
17068 TestCompletionCallback callback;
17069
tfarina42834112016-09-22 13:38:2017070 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117071 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417072
17073 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117074 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0417075
[email protected]79e1fd62013-06-20 06:50:0417076 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617077 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417078 EXPECT_TRUE(request_headers.HasHeader("Host"));
17079}
17080
bncd16676a2016-07-20 16:23:0117081TEST_F(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
[email protected]79e1fd62013-06-20 06:50:0417082 HttpRequestInfo request;
17083 request.method = "GET";
bncce36dca22015-04-21 22:11:2317084 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0417085 request.extra_headers.SetHeader("X-Foo", "bar");
Ramin Halavatib5e433e62018-02-07 07:41:1017086 request.traffic_annotation =
17087 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]79e1fd62013-06-20 06:50:0417088
danakj1fd259a02016-04-16 03:17:0917089 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617090 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]79e1fd62013-06-20 06:50:0417091
17092 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2317093 MockWrite(
17094 "GET / HTTP/1.1\r\n"
17095 "Host: www.example.org\r\n"
17096 "Connection: keep-alive\r\n"
17097 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0417098 };
17099 MockRead data_reads[] = {
17100 MockRead("HTTP/1.1 200 OK\r\n"
17101 "Content-Length: 5\r\n\r\n"
17102 "hello"),
17103 MockRead(ASYNC, ERR_UNEXPECTED),
17104 };
17105
Ryan Sleevib8d7ea02018-05-07 20:01:0117106 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]79e1fd62013-06-20 06:50:0417107 session_deps_.socket_factory->AddSocketDataProvider(&data);
17108
17109 TestCompletionCallback callback;
17110
tfarina42834112016-09-22 13:38:2017111 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117112 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0417113
17114 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117115 EXPECT_THAT(rv, IsOk());
[email protected]79e1fd62013-06-20 06:50:0417116
17117 HttpRequestHeaders request_headers;
bnc691fda62016-08-12 00:43:1617118 EXPECT_TRUE(trans.GetFullRequestHeaders(&request_headers));
[email protected]79e1fd62013-06-20 06:50:0417119 std::string foo;
17120 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
17121 EXPECT_EQ("bar", foo);
17122}
17123
[email protected]043b68c82013-08-22 23:41:5217124// Tests that when a used socket is returned to the SSL socket pool, it's closed
17125// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117126TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5217127 ClientSocketPoolManager::set_max_sockets_per_group(
17128 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17129 ClientSocketPoolManager::set_max_sockets_per_pool(
17130 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17131
17132 // Set up SSL request.
17133
17134 HttpRequestInfo ssl_request;
17135 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2317136 ssl_request.url = GURL("https://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017137 ssl_request.traffic_annotation =
17138 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217139
17140 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2317141 MockWrite(
17142 "GET / HTTP/1.1\r\n"
17143 "Host: www.example.org\r\n"
17144 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217145 };
17146 MockRead ssl_reads[] = {
17147 MockRead("HTTP/1.1 200 OK\r\n"),
17148 MockRead("Content-Length: 11\r\n\r\n"),
17149 MockRead("hello world"),
17150 MockRead(SYNCHRONOUS, OK),
17151 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117152 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
[email protected]043b68c82013-08-22 23:41:5217153 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17154
17155 SSLSocketDataProvider ssl(ASYNC, OK);
17156 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17157
17158 // Set up HTTP request.
17159
17160 HttpRequestInfo http_request;
17161 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317162 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017163 http_request.traffic_annotation =
17164 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217165
17166 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317167 MockWrite(
17168 "GET / HTTP/1.1\r\n"
17169 "Host: www.example.org\r\n"
17170 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217171 };
17172 MockRead http_reads[] = {
17173 MockRead("HTTP/1.1 200 OK\r\n"),
17174 MockRead("Content-Length: 7\r\n\r\n"),
17175 MockRead("falafel"),
17176 MockRead(SYNCHRONOUS, OK),
17177 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117178 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217179 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17180
danakj1fd259a02016-04-16 03:17:0917181 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217182
17183 // Start the SSL request.
17184 TestCompletionCallback ssl_callback;
bnc691fda62016-08-12 00:43:1617185 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017186 ASSERT_EQ(ERR_IO_PENDING,
17187 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
17188 NetLogWithSource()));
[email protected]043b68c82013-08-22 23:41:5217189
17190 // Start the HTTP request. Pool should stall.
17191 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617192 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017193 ASSERT_EQ(ERR_IO_PENDING,
17194 http_trans.Start(&http_request, http_callback.callback(),
17195 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117196 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217197
17198 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0117199 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217200 std::string response_data;
bnc691fda62016-08-12 00:43:1617201 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217202 EXPECT_EQ("hello world", response_data);
17203
17204 // The SSL socket should automatically be closed, so the HTTP request can
17205 // start.
Matt Menke9d5e2c92019-02-05 01:42:2317206 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
dcheng48459ac22014-08-26 00:46:4117207 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217208
17209 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0117210 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
bnc691fda62016-08-12 00:43:1617211 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217212 EXPECT_EQ("falafel", response_data);
17213
dcheng48459ac22014-08-26 00:46:4117214 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217215}
17216
17217// Tests that when a SSL connection is established but there's no corresponding
17218// request that needs it, the new socket is closed if the transport socket pool
17219// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0117220TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5217221 ClientSocketPoolManager::set_max_sockets_per_group(
17222 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17223 ClientSocketPoolManager::set_max_sockets_per_pool(
17224 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
17225
17226 // Set up an ssl request.
17227
17228 HttpRequestInfo ssl_request;
17229 ssl_request.method = "GET";
17230 ssl_request.url = GURL("https://www.foopy.com/");
Ramin Halavatib5e433e62018-02-07 07:41:1017231 ssl_request.traffic_annotation =
17232 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217233
17234 // No data will be sent on the SSL socket.
17235 StaticSocketDataProvider ssl_data;
17236 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
17237
17238 SSLSocketDataProvider ssl(ASYNC, OK);
17239 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17240
17241 // Set up HTTP request.
17242
17243 HttpRequestInfo http_request;
17244 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2317245 http_request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017246 http_request.traffic_annotation =
17247 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]043b68c82013-08-22 23:41:5217248
17249 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2317250 MockWrite(
17251 "GET / HTTP/1.1\r\n"
17252 "Host: www.example.org\r\n"
17253 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5217254 };
17255 MockRead http_reads[] = {
17256 MockRead("HTTP/1.1 200 OK\r\n"),
17257 MockRead("Content-Length: 7\r\n\r\n"),
17258 MockRead("falafel"),
17259 MockRead(SYNCHRONOUS, OK),
17260 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117261 StaticSocketDataProvider http_data(http_reads, http_writes);
[email protected]043b68c82013-08-22 23:41:5217262 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
17263
danakj1fd259a02016-04-16 03:17:0917264 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5217265
17266 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
17267 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2917268 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5917269 http_stream_factory->PreconnectStreams(1, ssl_request);
Matt Menke9d5e2c92019-02-05 01:42:2317270 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217271
17272 // Start the HTTP request. Pool should stall.
17273 TestCompletionCallback http_callback;
bnc691fda62016-08-12 00:43:1617274 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017275 ASSERT_EQ(ERR_IO_PENDING,
17276 http_trans.Start(&http_request, http_callback.callback(),
17277 NetLogWithSource()));
dcheng48459ac22014-08-26 00:46:4117278 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5217279
17280 // The SSL connection will automatically be closed once the connection is
17281 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0117282 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5217283 std::string response_data;
bnc691fda62016-08-12 00:43:1617284 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5217285 EXPECT_EQ("falafel", response_data);
17286
dcheng48459ac22014-08-26 00:46:4117287 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5217288}
17289
bncd16676a2016-07-20 16:23:0117290TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917291 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217292 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917293 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217294 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417295
17296 HttpRequestInfo request;
17297 request.method = "POST";
17298 request.url = GURL("http://www.foo.com/");
17299 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017300 request.traffic_annotation =
17301 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417302
danakj1fd259a02016-04-16 03:17:0917303 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617304 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417305 // Send headers successfully, but get an error while sending the body.
17306 MockWrite data_writes[] = {
17307 MockWrite("POST / HTTP/1.1\r\n"
17308 "Host: www.foo.com\r\n"
17309 "Connection: keep-alive\r\n"
17310 "Content-Length: 3\r\n\r\n"),
17311 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17312 };
17313
17314 MockRead data_reads[] = {
17315 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17316 MockRead("hello world"),
17317 MockRead(SYNCHRONOUS, OK),
17318 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117319 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417320 session_deps_.socket_factory->AddSocketDataProvider(&data);
17321
17322 TestCompletionCallback callback;
17323
tfarina42834112016-09-22 13:38:2017324 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417326
17327 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117328 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417329
bnc691fda62016-08-12 00:43:1617330 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217331 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417332
wezca1070932016-05-26 20:30:5217333 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417334 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17335
17336 std::string response_data;
bnc691fda62016-08-12 00:43:1617337 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117338 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417339 EXPECT_EQ("hello world", response_data);
17340}
17341
17342// This test makes sure the retry logic doesn't trigger when reading an error
17343// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0117344TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417345 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0917346 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5417347 MockWrite data_writes[] = {
17348 MockWrite("GET / HTTP/1.1\r\n"
17349 "Host: www.foo.com\r\n"
17350 "Connection: keep-alive\r\n\r\n"),
17351 MockWrite("POST / HTTP/1.1\r\n"
17352 "Host: www.foo.com\r\n"
17353 "Connection: keep-alive\r\n"
17354 "Content-Length: 3\r\n\r\n"),
17355 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17356 };
17357
17358 MockRead data_reads[] = {
17359 MockRead("HTTP/1.1 200 Peachy\r\n"
17360 "Content-Length: 14\r\n\r\n"),
17361 MockRead("first response"),
17362 MockRead("HTTP/1.1 400 Not OK\r\n"
17363 "Content-Length: 15\r\n\r\n"),
17364 MockRead("second response"),
17365 MockRead(SYNCHRONOUS, OK),
17366 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117367 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417368 session_deps_.socket_factory->AddSocketDataProvider(&data);
17369
17370 TestCompletionCallback callback;
17371 HttpRequestInfo request1;
17372 request1.method = "GET";
17373 request1.url = GURL("http://www.foo.com/");
17374 request1.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017375 request1.traffic_annotation =
17376 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417377
bnc87dcefc2017-05-25 12:47:5817378 auto trans1 =
Jeremy Roman0579ed62017-08-29 15:56:1917379 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017380 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117381 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417382
17383 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117384 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417385
17386 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5217387 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5417388
wezca1070932016-05-26 20:30:5217389 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5417390 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
17391
17392 std::string response_data1;
17393 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0117394 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417395 EXPECT_EQ("first response", response_data1);
17396 // Delete the transaction to release the socket back into the socket pool.
17397 trans1.reset();
17398
danakj1fd259a02016-04-16 03:17:0917399 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217400 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917401 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217402 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417403
17404 HttpRequestInfo request2;
17405 request2.method = "POST";
17406 request2.url = GURL("http://www.foo.com/");
17407 request2.upload_data_stream = &upload_data_stream;
17408 request2.load_flags = 0;
Ramin Halavatib5e433e62018-02-07 07:41:1017409 request2.traffic_annotation =
17410 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417411
bnc691fda62016-08-12 00:43:1617412 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
tfarina42834112016-09-22 13:38:2017413 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117414 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417415
17416 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117417 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417418
bnc691fda62016-08-12 00:43:1617419 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5217420 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5417421
wezca1070932016-05-26 20:30:5217422 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5417423 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
17424
17425 std::string response_data2;
bnc691fda62016-08-12 00:43:1617426 rv = ReadTransaction(&trans2, &response_data2);
robpercival214763f2016-07-01 23:27:0117427 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417428 EXPECT_EQ("second response", response_data2);
17429}
17430
bncd16676a2016-07-20 16:23:0117431TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417432 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0917433 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217434 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917435 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217436 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417437
17438 HttpRequestInfo request;
17439 request.method = "POST";
17440 request.url = GURL("http://www.foo.com/");
17441 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017442 request.traffic_annotation =
17443 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417444
danakj1fd259a02016-04-16 03:17:0917445 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617446 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417447 // Send headers successfully, but get an error while sending the body.
17448 MockWrite data_writes[] = {
17449 MockWrite("POST / HTTP/1.1\r\n"
17450 "Host: www.foo.com\r\n"
17451 "Connection: keep-alive\r\n"
17452 "Content-Length: 3\r\n\r\n"
17453 "fo"),
17454 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17455 };
17456
17457 MockRead data_reads[] = {
17458 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17459 MockRead("hello world"),
17460 MockRead(SYNCHRONOUS, OK),
17461 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117462 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417463 session_deps_.socket_factory->AddSocketDataProvider(&data);
17464
17465 TestCompletionCallback callback;
17466
tfarina42834112016-09-22 13:38:2017467 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117468 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417469
17470 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117471 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417472
bnc691fda62016-08-12 00:43:1617473 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217474 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417475
wezca1070932016-05-26 20:30:5217476 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417477 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17478
17479 std::string response_data;
bnc691fda62016-08-12 00:43:1617480 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117481 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417482 EXPECT_EQ("hello world", response_data);
17483}
17484
17485// This tests the more common case than the previous test, where headers and
17486// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0117487TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0717488 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5417489
17490 HttpRequestInfo request;
17491 request.method = "POST";
17492 request.url = GURL("http://www.foo.com/");
17493 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017494 request.traffic_annotation =
17495 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417496
danakj1fd259a02016-04-16 03:17:0917497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617498 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417499 // Send headers successfully, but get an error while sending the body.
17500 MockWrite data_writes[] = {
17501 MockWrite("POST / HTTP/1.1\r\n"
17502 "Host: www.foo.com\r\n"
17503 "Connection: keep-alive\r\n"
17504 "Transfer-Encoding: chunked\r\n\r\n"),
17505 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17506 };
17507
17508 MockRead data_reads[] = {
17509 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17510 MockRead("hello world"),
17511 MockRead(SYNCHRONOUS, OK),
17512 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117513 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417514 session_deps_.socket_factory->AddSocketDataProvider(&data);
17515
17516 TestCompletionCallback callback;
17517
tfarina42834112016-09-22 13:38:2017518 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117519 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417520 // Make sure the headers are sent before adding a chunk. This ensures that
17521 // they can't be merged with the body in a single send. Not currently
17522 // necessary since a chunked body is never merged with headers, but this makes
17523 // the test more future proof.
17524 base::RunLoop().RunUntilIdle();
17525
mmenkecbc2b712014-10-09 20:29:0717526 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5417527
17528 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117529 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417530
bnc691fda62016-08-12 00:43:1617531 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217532 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417533
wezca1070932016-05-26 20:30:5217534 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417535 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17536
17537 std::string response_data;
bnc691fda62016-08-12 00:43:1617538 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117539 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417540 EXPECT_EQ("hello world", response_data);
17541}
17542
bncd16676a2016-07-20 16:23:0117543TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917544 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217545 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917546 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217547 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417548
17549 HttpRequestInfo request;
17550 request.method = "POST";
17551 request.url = GURL("http://www.foo.com/");
17552 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017553 request.traffic_annotation =
17554 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417555
danakj1fd259a02016-04-16 03:17:0917556 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617557 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417558
17559 MockWrite data_writes[] = {
17560 MockWrite("POST / HTTP/1.1\r\n"
17561 "Host: www.foo.com\r\n"
17562 "Connection: keep-alive\r\n"
17563 "Content-Length: 3\r\n\r\n"),
17564 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17565 };
17566
17567 MockRead data_reads[] = {
17568 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17569 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
17570 MockRead("hello world"),
17571 MockRead(SYNCHRONOUS, OK),
17572 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117573 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417574 session_deps_.socket_factory->AddSocketDataProvider(&data);
17575
17576 TestCompletionCallback callback;
17577
tfarina42834112016-09-22 13:38:2017578 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117579 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417580
17581 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117582 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417583
bnc691fda62016-08-12 00:43:1617584 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5217585 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5417586
wezca1070932016-05-26 20:30:5217587 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5417588 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
17589
17590 std::string response_data;
bnc691fda62016-08-12 00:43:1617591 rv = ReadTransaction(&trans, &response_data);
robpercival214763f2016-07-01 23:27:0117592 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5417593 EXPECT_EQ("hello world", response_data);
17594}
17595
bncd16676a2016-07-20 16:23:0117596TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917597 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217598 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917599 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217600 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417601
17602 HttpRequestInfo request;
17603 request.method = "POST";
17604 request.url = GURL("http://www.foo.com/");
17605 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017606 request.traffic_annotation =
17607 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417608
danakj1fd259a02016-04-16 03:17:0917609 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617610 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417611 // Send headers successfully, but get an error while sending the body.
17612 MockWrite data_writes[] = {
17613 MockWrite("POST / HTTP/1.1\r\n"
17614 "Host: www.foo.com\r\n"
17615 "Connection: keep-alive\r\n"
17616 "Content-Length: 3\r\n\r\n"),
17617 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17618 };
17619
17620 MockRead data_reads[] = {
17621 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
17622 MockRead("hello world"),
17623 MockRead(SYNCHRONOUS, OK),
17624 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117625 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417626 session_deps_.socket_factory->AddSocketDataProvider(&data);
17627
17628 TestCompletionCallback callback;
17629
tfarina42834112016-09-22 13:38:2017630 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117631 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417632
17633 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117634 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417635}
17636
bncd16676a2016-07-20 16:23:0117637TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5417638 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0917639 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217640 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917641 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217642 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417643
17644 HttpRequestInfo request;
17645 request.method = "POST";
17646 request.url = GURL("http://www.foo.com/");
17647 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017648 request.traffic_annotation =
17649 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417650
danakj1fd259a02016-04-16 03:17:0917651 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617652 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417653 // Send headers successfully, but get an error while sending the body.
17654 MockWrite data_writes[] = {
17655 MockWrite("POST / HTTP/1.1\r\n"
17656 "Host: www.foo.com\r\n"
17657 "Connection: keep-alive\r\n"
17658 "Content-Length: 3\r\n\r\n"),
17659 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17660 };
17661
17662 MockRead data_reads[] = {
17663 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
17664 MockRead("HTTP/1.0 302 Redirect\r\n"),
17665 MockRead("Location: http://somewhere-else.com/\r\n"),
17666 MockRead("Content-Length: 0\r\n\r\n"),
17667 MockRead(SYNCHRONOUS, OK),
17668 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117669 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417670 session_deps_.socket_factory->AddSocketDataProvider(&data);
17671
17672 TestCompletionCallback callback;
17673
tfarina42834112016-09-22 13:38:2017674 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117675 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417676
17677 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117678 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417679}
17680
bncd16676a2016-07-20 16:23:0117681TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0917682 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217683 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917684 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217685 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417686
17687 HttpRequestInfo request;
17688 request.method = "POST";
17689 request.url = GURL("http://www.foo.com/");
17690 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017691 request.traffic_annotation =
17692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417693
danakj1fd259a02016-04-16 03:17:0917694 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617695 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417696 // Send headers successfully, but get an error while sending the body.
17697 MockWrite data_writes[] = {
17698 MockWrite("POST / HTTP/1.1\r\n"
17699 "Host: www.foo.com\r\n"
17700 "Connection: keep-alive\r\n"
17701 "Content-Length: 3\r\n\r\n"),
17702 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17703 };
17704
17705 MockRead data_reads[] = {
17706 MockRead("HTTP 0.9 rocks!"),
17707 MockRead(SYNCHRONOUS, OK),
17708 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117709 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417710 session_deps_.socket_factory->AddSocketDataProvider(&data);
17711
17712 TestCompletionCallback callback;
17713
tfarina42834112016-09-22 13:38:2017714 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117715 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417716
17717 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117718 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417719}
17720
bncd16676a2016-07-20 16:23:0117721TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0917722 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2217723 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1917724 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2217725 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5417726
17727 HttpRequestInfo request;
17728 request.method = "POST";
17729 request.url = GURL("http://www.foo.com/");
17730 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1017731 request.traffic_annotation =
17732 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
[email protected]02d74a02014-04-23 18:10:5417733
danakj1fd259a02016-04-16 03:17:0917734 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1617735 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]02d74a02014-04-23 18:10:5417736 // Send headers successfully, but get an error while sending the body.
17737 MockWrite data_writes[] = {
17738 MockWrite("POST / HTTP/1.1\r\n"
17739 "Host: www.foo.com\r\n"
17740 "Connection: keep-alive\r\n"
17741 "Content-Length: 3\r\n\r\n"),
17742 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
17743 };
17744
17745 MockRead data_reads[] = {
17746 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
17747 MockRead(SYNCHRONOUS, OK),
17748 };
Ryan Sleevib8d7ea02018-05-07 20:01:0117749 StaticSocketDataProvider data(data_reads, data_writes);
[email protected]02d74a02014-04-23 18:10:5417750 session_deps_.socket_factory->AddSocketDataProvider(&data);
17751
17752 TestCompletionCallback callback;
17753
tfarina42834112016-09-22 13:38:2017754 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117755 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5417756
17757 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117758 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5417759}
17760
Bence Békydca6bd92018-01-30 13:43:0617761#if BUILDFLAG(ENABLE_WEBSOCKETS)
17762
17763namespace {
17764
17765void AddWebSocketHeaders(HttpRequestHeaders* headers) {
17766 headers->SetHeader("Connection", "Upgrade");
17767 headers->SetHeader("Upgrade", "websocket");
17768 headers->SetHeader("Origin", "http://www.example.org");
17769 headers->SetHeader("Sec-WebSocket-Version", "13");
Bence Békydca6bd92018-01-30 13:43:0617770}
17771
17772} // namespace
17773
17774TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
Bence Béky2fcf4fa2018-04-06 20:06:0117775 for (bool secure : {true, false}) {
17776 MockWrite data_writes[] = {
17777 MockWrite("GET / HTTP/1.1\r\n"
17778 "Host: www.example.org\r\n"
17779 "Connection: Upgrade\r\n"
17780 "Upgrade: websocket\r\n"
17781 "Origin: http://www.example.org\r\n"
17782 "Sec-WebSocket-Version: 13\r\n"
17783 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17784 "Sec-WebSocket-Extensions: permessage-deflate; "
17785 "client_max_window_bits\r\n\r\n")};
17786
17787 MockRead data_reads[] = {
17788 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17789 "Upgrade: websocket\r\n"
17790 "Connection: Upgrade\r\n"
17791 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
17792
Ryan Sleevib8d7ea02018-05-07 20:01:0117793 StaticSocketDataProvider data(data_reads, data_writes);
Bence Béky2fcf4fa2018-04-06 20:06:0117794 session_deps_.socket_factory->AddSocketDataProvider(&data);
17795 SSLSocketDataProvider ssl(ASYNC, OK);
17796 if (secure)
17797 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
Bence Békydca6bd92018-01-30 13:43:0617798
17799 HttpRequestInfo request;
17800 request.method = "GET";
Bence Béky2fcf4fa2018-04-06 20:06:0117801 request.url =
17802 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
17803 AddWebSocketHeaders(&request.extra_headers);
Ramin Halavatib5e433e62018-02-07 07:41:1017804 request.traffic_annotation =
17805 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Bence Békydca6bd92018-01-30 13:43:0617806
Bence Béky2fcf4fa2018-04-06 20:06:0117807 TestWebSocketHandshakeStreamCreateHelper
17808 websocket_handshake_stream_create_helper;
Bence Béky8d1c6052018-02-07 12:48:1517809
Bence Béky2fcf4fa2018-04-06 20:06:0117810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Bence Békydca6bd92018-01-30 13:43:0617811 HttpNetworkTransaction trans(LOW, session.get());
17812 trans.SetWebSocketHandshakeStreamCreateHelper(
Bence Béky2fcf4fa2018-04-06 20:06:0117813 &websocket_handshake_stream_create_helper);
Bence Békydca6bd92018-01-30 13:43:0617814
17815 TestCompletionCallback callback;
Bence Béky2fcf4fa2018-04-06 20:06:0117816 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
17817 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Bence Békydca6bd92018-01-30 13:43:0617818
Bence Béky2fcf4fa2018-04-06 20:06:0117819 const HttpStreamRequest* stream_request = trans.stream_request_.get();
17820 ASSERT_TRUE(stream_request);
17821 EXPECT_EQ(&websocket_handshake_stream_create_helper,
17822 stream_request->websocket_handshake_stream_create_helper());
17823
17824 rv = callback.WaitForResult();
17825 EXPECT_THAT(rv, IsOk());
17826
17827 EXPECT_TRUE(data.AllReadDataConsumed());
17828 EXPECT_TRUE(data.AllWriteDataConsumed());
Bence Békydca6bd92018-01-30 13:43:0617829 }
17830}
17831
Adam Rice425cf122015-01-19 06:18:2417832// Verify that proxy headers are not sent to the destination server when
17833// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0117834TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2417835 HttpRequestInfo request;
17836 request.method = "GET";
bncce36dca22015-04-21 22:11:2317837 request.url = GURL("wss://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017838 request.traffic_annotation =
17839 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417840 AddWebSocketHeaders(&request.extra_headers);
17841
17842 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5917843 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917844 ProxyResolutionService::CreateFixedFromPacResult(
17845 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417846
danakj1fd259a02016-04-16 03:17:0917847 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2417848
17849 // Since a proxy is configured, try to establish a tunnel.
17850 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1717851 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17852 "Host: www.example.org:443\r\n"
17853 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417854
17855 // After calling trans->RestartWithAuth(), this is the request we should
17856 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1717857 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
17858 "Host: www.example.org:443\r\n"
17859 "Proxy-Connection: keep-alive\r\n"
17860 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417861
rsleevidb16bb02015-11-12 23:47:1717862 MockWrite("GET / HTTP/1.1\r\n"
17863 "Host: www.example.org\r\n"
17864 "Connection: Upgrade\r\n"
17865 "Upgrade: websocket\r\n"
17866 "Origin: http://www.example.org\r\n"
17867 "Sec-WebSocket-Version: 13\r\n"
Bence Béky8d1c6052018-02-07 12:48:1517868 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17869 "Sec-WebSocket-Extensions: permessage-deflate; "
17870 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417871
17872 // The proxy responds to the connect with a 407, using a persistent
17873 // connection.
17874 MockRead data_reads[] = {
17875 // No credentials.
Bence Béky8d1c6052018-02-07 12:48:1517876 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
17877 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
17878 "Content-Length: 0\r\n"
17879 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417880
17881 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
17882
Bence Béky8d1c6052018-02-07 12:48:1517883 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17884 "Upgrade: websocket\r\n"
17885 "Connection: Upgrade\r\n"
17886 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417887
Ryan Sleevib8d7ea02018-05-07 20:01:0117888 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2417889 session_deps_.socket_factory->AddSocketDataProvider(&data);
17890 SSLSocketDataProvider ssl(ASYNC, OK);
17891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17892
Bence Béky8d1c6052018-02-07 12:48:1517893 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
17894
bnc87dcefc2017-05-25 12:47:5817895 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917896 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2417897 trans->SetWebSocketHandshakeStreamCreateHelper(
17898 &websocket_stream_create_helper);
17899
17900 {
17901 TestCompletionCallback callback;
17902
tfarina42834112016-09-22 13:38:2017903 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0117904 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2417905
17906 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117907 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2417908 }
17909
17910 const HttpResponseInfo* response = trans->GetResponseInfo();
17911 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5217912 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2417913 EXPECT_EQ(407, response->headers->response_code());
17914
17915 {
17916 TestCompletionCallback callback;
17917
17918 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
17919 callback.callback());
robpercival214763f2016-07-01 23:27:0117920 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2417921
17922 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0117923 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2417924 }
17925
17926 response = trans->GetResponseInfo();
17927 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5217928 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2417929
17930 EXPECT_EQ(101, response->headers->response_code());
17931
17932 trans.reset();
17933 session->CloseAllConnections();
17934}
17935
17936// Verify that proxy headers are not sent to the destination server when
17937// establishing a tunnel for an insecure WebSocket connection.
17938// This requires the authentication info to be injected into the auth cache
17939// due to crbug.com/395064
17940// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0117941TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2417942 HttpRequestInfo request;
17943 request.method = "GET";
bncce36dca22015-04-21 22:11:2317944 request.url = GURL("ws://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1017945 request.traffic_annotation =
17946 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417947 AddWebSocketHeaders(&request.extra_headers);
17948
17949 // Configure against proxy server "myproxy:70".
Lily Houghton8c2f97d2018-01-22 05:06:5917950 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4917951 ProxyResolutionService::CreateFixedFromPacResult(
17952 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
Adam Rice425cf122015-01-19 06:18:2417953
danakj1fd259a02016-04-16 03:17:0917954 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2417955
17956 MockWrite data_writes[] = {
17957 // Try to establish a tunnel for the WebSocket connection, with
17958 // credentials. Because WebSockets have a separate set of socket pools,
17959 // they cannot and will not use the same TCP/IP connection as the
17960 // preflight HTTP request.
Bence Béky8d1c6052018-02-07 12:48:1517961 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
17962 "Host: www.example.org:80\r\n"
17963 "Proxy-Connection: keep-alive\r\n"
17964 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2417965
Bence Béky8d1c6052018-02-07 12:48:1517966 MockWrite("GET / HTTP/1.1\r\n"
17967 "Host: www.example.org\r\n"
17968 "Connection: Upgrade\r\n"
17969 "Upgrade: websocket\r\n"
17970 "Origin: http://www.example.org\r\n"
17971 "Sec-WebSocket-Version: 13\r\n"
17972 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
17973 "Sec-WebSocket-Extensions: permessage-deflate; "
17974 "client_max_window_bits\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417975
17976 MockRead data_reads[] = {
17977 // HTTP CONNECT with credentials.
17978 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
17979
17980 // WebSocket connection established inside tunnel.
Bence Béky8d1c6052018-02-07 12:48:1517981 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
17982 "Upgrade: websocket\r\n"
17983 "Connection: Upgrade\r\n"
17984 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
Adam Rice425cf122015-01-19 06:18:2417985
Ryan Sleevib8d7ea02018-05-07 20:01:0117986 StaticSocketDataProvider data(data_reads, data_writes);
Adam Rice425cf122015-01-19 06:18:2417987 session_deps_.socket_factory->AddSocketDataProvider(&data);
17988
17989 session->http_auth_cache()->Add(
17990 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
17991 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
17992
Bence Béky8d1c6052018-02-07 12:48:1517993 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
17994
bnc87dcefc2017-05-25 12:47:5817995 auto trans =
Jeremy Roman0579ed62017-08-29 15:56:1917996 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Adam Rice425cf122015-01-19 06:18:2417997 trans->SetWebSocketHandshakeStreamCreateHelper(
17998 &websocket_stream_create_helper);
17999
18000 TestCompletionCallback callback;
18001
tfarina42834112016-09-22 13:38:2018002 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
robpercival214763f2016-07-01 23:27:0118003 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2418004
18005 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0118006 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2418007
18008 const HttpResponseInfo* response = trans->GetResponseInfo();
18009 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5218010 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2418011
18012 EXPECT_EQ(101, response->headers->response_code());
18013
18014 trans.reset();
18015 session->CloseAllConnections();
18016}
18017
Matt Menke1d6093e32019-03-22 17:33:4318018// WebSockets over QUIC is not supported, including over QUIC proxies.
18019TEST_F(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
18020 for (bool secure : {true, false}) {
18021 SCOPED_TRACE(secure);
18022 session_deps_.proxy_resolution_service =
18023 ProxyResolutionService::CreateFixedFromPacResult(
18024 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
18025 session_deps_.enable_quic = true;
18026
18027 HttpRequestInfo request;
18028 request.url =
18029 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
18030 AddWebSocketHeaders(&request.extra_headers);
18031 request.traffic_annotation =
18032 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18033
18034 TestWebSocketHandshakeStreamCreateHelper
18035 websocket_handshake_stream_create_helper;
18036
18037 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18038 HttpNetworkTransaction trans(LOW, session.get());
18039 trans.SetWebSocketHandshakeStreamCreateHelper(
18040 &websocket_handshake_stream_create_helper);
18041
18042 TestCompletionCallback callback;
18043 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18044 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18045
18046 rv = callback.WaitForResult();
18047 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
18048 }
18049}
18050
Bence Békydca6bd92018-01-30 13:43:0618051#endif // BUILDFLAG(ENABLE_WEBSOCKETS)
18052
bncd16676a2016-07-20 16:23:0118053TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0918054 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218055 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918056 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218057 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218058
18059 HttpRequestInfo request;
18060 request.method = "POST";
18061 request.url = GURL("http://www.foo.com/");
18062 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018063 request.traffic_annotation =
18064 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218065
danakj1fd259a02016-04-16 03:17:0918066 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618067 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218068 MockWrite data_writes[] = {
18069 MockWrite("POST / HTTP/1.1\r\n"
18070 "Host: www.foo.com\r\n"
18071 "Connection: keep-alive\r\n"
18072 "Content-Length: 3\r\n\r\n"),
18073 MockWrite("foo"),
18074 };
18075
18076 MockRead data_reads[] = {
18077 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18078 MockRead(SYNCHRONOUS, OK),
18079 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118080 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218081 session_deps_.socket_factory->AddSocketDataProvider(&data);
18082
18083 TestCompletionCallback callback;
18084
18085 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018086 trans.Start(&request, callback.callback(), NetLogWithSource()));
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
bncd16676a2016-07-20 16:23:0118096TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0918097 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2218098 element_readers.push_back(
Jeremy Roman0579ed62017-08-29 15:56:1918099 std::make_unique<UploadBytesElementReader>("foo", 3));
olli.raula6df48b2a2015-11-26 07:40:2218100 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2218101
18102 HttpRequestInfo request;
18103 request.method = "POST";
18104 request.url = GURL("http://www.foo.com/");
18105 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018106 request.traffic_annotation =
18107 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218108
danakj1fd259a02016-04-16 03:17:0918109 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618110 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218111 MockWrite data_writes[] = {
18112 MockWrite("POST / HTTP/1.1\r\n"
18113 "Host: www.foo.com\r\n"
18114 "Connection: keep-alive\r\n"
18115 "Content-Length: 3\r\n\r\n"),
18116 MockWrite("foo"),
18117 };
18118
18119 MockRead data_reads[] = {
18120 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
18121 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18122 MockRead(SYNCHRONOUS, OK),
18123 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118124 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218125 session_deps_.socket_factory->AddSocketDataProvider(&data);
18126
18127 TestCompletionCallback callback;
18128
18129 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018130 trans.Start(&request, callback.callback(), NetLogWithSource()));
robpercival214763f2016-07-01 23:27:0118131 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218132
18133 std::string response_data;
bnc691fda62016-08-12 00:43:1618134 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218135
Ryan Sleevib8d7ea02018-05-07 20:01:0118136 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18137 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218138}
18139
bncd16676a2016-07-20 16:23:0118140TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2218141 ChunkedUploadDataStream upload_data_stream(0);
18142
18143 HttpRequestInfo request;
18144 request.method = "POST";
18145 request.url = GURL("http://www.foo.com/");
18146 request.upload_data_stream = &upload_data_stream;
Ramin Halavatib5e433e62018-02-07 07:41:1018147 request.traffic_annotation =
18148 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
sclittlefb249892015-09-10 21:33:2218149
danakj1fd259a02016-04-16 03:17:0918150 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc691fda62016-08-12 00:43:1618151 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
sclittlefb249892015-09-10 21:33:2218152 // Send headers successfully, but get an error while sending the body.
18153 MockWrite data_writes[] = {
18154 MockWrite("POST / HTTP/1.1\r\n"
18155 "Host: www.foo.com\r\n"
18156 "Connection: keep-alive\r\n"
18157 "Transfer-Encoding: chunked\r\n\r\n"),
18158 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
18159 };
18160
18161 MockRead data_reads[] = {
18162 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
18163 MockRead(SYNCHRONOUS, OK),
18164 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118165 StaticSocketDataProvider data(data_reads, data_writes);
sclittlefb249892015-09-10 21:33:2218166 session_deps_.socket_factory->AddSocketDataProvider(&data);
18167
18168 TestCompletionCallback callback;
18169
18170 EXPECT_EQ(ERR_IO_PENDING,
tfarina42834112016-09-22 13:38:2018171 trans.Start(&request, callback.callback(), NetLogWithSource()));
sclittlefb249892015-09-10 21:33:2218172
18173 base::RunLoop().RunUntilIdle();
18174 upload_data_stream.AppendData("f", 1, false);
18175
18176 base::RunLoop().RunUntilIdle();
18177 upload_data_stream.AppendData("oo", 2, true);
18178
robpercival214763f2016-07-01 23:27:0118179 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2218180
18181 std::string response_data;
bnc691fda62016-08-12 00:43:1618182 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2218183
Ryan Sleevib8d7ea02018-05-07 20:01:0118184 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
18185 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
sclittlefb249892015-09-10 21:33:2218186}
18187
eustasc7d27da2017-04-06 10:33:2018188void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
18189 const std::string& accept_encoding,
18190 const std::string& content_encoding,
sky50576f32017-05-01 19:28:0318191 const std::string& location,
eustasc7d27da2017-04-06 10:33:2018192 bool should_match) {
18193 HttpRequestInfo request;
18194 request.method = "GET";
18195 request.url = GURL("http://www.foo.com/");
18196 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
18197 accept_encoding);
Ramin Halavatib5e433e62018-02-07 07:41:1018198 request.traffic_annotation =
18199 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
eustasc7d27da2017-04-06 10:33:2018200
18201 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
18202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18203 // Send headers successfully, but get an error while sending the body.
18204 MockWrite data_writes[] = {
18205 MockWrite("GET / HTTP/1.1\r\n"
18206 "Host: www.foo.com\r\n"
18207 "Connection: keep-alive\r\n"
18208 "Accept-Encoding: "),
18209 MockWrite(accept_encoding.data()), MockWrite("\r\n\r\n"),
18210 };
18211
sky50576f32017-05-01 19:28:0318212 std::string response_code = "200 OK";
18213 std::string extra;
18214 if (!location.empty()) {
18215 response_code = "301 Redirect\r\nLocation: ";
18216 response_code.append(location);
18217 }
18218
eustasc7d27da2017-04-06 10:33:2018219 MockRead data_reads[] = {
sky50576f32017-05-01 19:28:0318220 MockRead("HTTP/1.0 "),
18221 MockRead(response_code.data()),
18222 MockRead("\r\nContent-Encoding: "),
18223 MockRead(content_encoding.data()),
18224 MockRead("\r\n\r\n"),
eustasc7d27da2017-04-06 10:33:2018225 MockRead(SYNCHRONOUS, OK),
18226 };
Ryan Sleevib8d7ea02018-05-07 20:01:0118227 StaticSocketDataProvider data(data_reads, data_writes);
eustasc7d27da2017-04-06 10:33:2018228 session_deps->socket_factory->AddSocketDataProvider(&data);
18229
18230 TestCompletionCallback callback;
18231
18232 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18233 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18234
18235 rv = callback.WaitForResult();
18236 if (should_match) {
18237 EXPECT_THAT(rv, IsOk());
18238 } else {
18239 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
18240 }
18241}
18242
18243TEST_F(HttpNetworkTransactionTest, MatchContentEncoding1) {
sky50576f32017-05-01 19:28:0318244 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
eustasc7d27da2017-04-06 10:33:2018245}
18246
18247TEST_F(HttpNetworkTransactionTest, MatchContentEncoding2) {
sky50576f32017-05-01 19:28:0318248 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
18249 true);
eustasc7d27da2017-04-06 10:33:2018250}
18251
18252TEST_F(HttpNetworkTransactionTest, MatchContentEncoding3) {
18253 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
sky50576f32017-05-01 19:28:0318254 "", false);
18255}
18256
18257TEST_F(HttpNetworkTransactionTest, MatchContentEncoding4) {
18258 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
18259 "www.foo.com/other", true);
eustasc7d27da2017-04-06 10:33:2018260}
18261
xunjieli96f2a402017-06-05 17:24:2718262TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
18263 ProxyConfig proxy_config;
18264 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18265 proxy_config.set_pac_mandatory(true);
18266 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918267 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918268 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18269 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Bence Béky8f9d7d3952017-10-09 19:58:0418270 std::make_unique<FailingProxyResolverFactory>(), nullptr));
xunjieli96f2a402017-06-05 17:24:2718271
18272 HttpRequestInfo request;
18273 request.method = "GET";
18274 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018275 request.traffic_annotation =
18276 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718277
18278 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18279 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18280
18281 TestCompletionCallback callback;
18282
18283 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18284 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18285 EXPECT_THAT(callback.WaitForResult(),
18286 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18287}
18288
18289TEST_F(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
18290 ProxyConfig proxy_config;
18291 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
18292 proxy_config.set_pac_mandatory(true);
18293 MockAsyncProxyResolverFactory* proxy_resolver_factory =
18294 new MockAsyncProxyResolverFactory(false);
18295 MockAsyncProxyResolver resolver;
Lily Houghton8c2f97d2018-01-22 05:06:5918296 session_deps_.proxy_resolution_service.reset(new ProxyResolutionService(
Ramin Halavatica8d5252018-03-12 05:33:4918297 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
18298 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
Lily Houghton8c2f97d2018-01-22 05:06:5918299 base::WrapUnique(proxy_resolver_factory), nullptr));
xunjieli96f2a402017-06-05 17:24:2718300 HttpRequestInfo request;
18301 request.method = "GET";
18302 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018303 request.traffic_annotation =
18304 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718305
18306 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18307 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18308
18309 TestCompletionCallback callback;
18310 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18311 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18312
18313 proxy_resolver_factory->pending_requests()[0]->CompleteNowWithForwarder(
18314 ERR_FAILED, &resolver);
18315 EXPECT_THAT(callback.WaitForResult(),
18316 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
18317}
18318
18319TEST_F(HttpNetworkTransactionTest, NoSupportedProxies) {
Lily Houghton8c2f97d2018-01-22 05:06:5918320 session_deps_.proxy_resolution_service =
Ramin Halavatica8d5252018-03-12 05:33:4918321 ProxyResolutionService::CreateFixedFromPacResult(
18322 "QUIC myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718323 session_deps_.enable_quic = false;
18324 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18325
18326 HttpRequestInfo request;
18327 request.method = "GET";
18328 request.url = GURL("http://www.example.org/");
Ramin Halavatib5e433e62018-02-07 07:41:1018329 request.traffic_annotation =
18330 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli96f2a402017-06-05 17:24:2718331
18332 TestCompletionCallback callback;
18333 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18334 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18335 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18336
18337 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
18338}
18339
Douglas Creager3cb042052018-11-06 23:08:5218340//-----------------------------------------------------------------------------
Douglas Creager134b52e2018-11-09 18:00:1418341// Reporting tests
18342
18343#if BUILDFLAG(ENABLE_REPORTING)
18344class HttpNetworkTransactionReportingTest : public HttpNetworkTransactionTest {
18345 protected:
18346 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618347 HttpNetworkTransactionTest::SetUp();
Douglas Creager134b52e2018-11-09 18:00:1418348 auto test_reporting_context = std::make_unique<TestReportingContext>(
18349 &clock_, &tick_clock_, ReportingPolicy());
18350 test_reporting_context_ = test_reporting_context.get();
18351 session_deps_.reporting_service =
18352 ReportingService::CreateForTesting(std::move(test_reporting_context));
18353 }
18354
18355 TestReportingContext* reporting_context() const {
18356 return test_reporting_context_;
18357 }
18358
18359 void clear_reporting_service() {
18360 session_deps_.reporting_service.reset();
18361 test_reporting_context_ = nullptr;
18362 }
18363
18364 // Makes an HTTPS request that should install a valid Reporting policy.
Lily Chenfec60d92019-01-24 01:16:4218365 void RequestPolicy(CertStatus cert_status = 0) {
18366 HttpRequestInfo request;
18367 request.method = "GET";
18368 request.url = GURL(url_);
18369 request.traffic_annotation =
18370 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18371
Lily Chend3930e72019-03-01 19:31:1118372 MockWrite data_writes[] = {
18373 MockWrite("GET / HTTP/1.1\r\n"
18374 "Host: www.example.org\r\n"
18375 "Connection: keep-alive\r\n\r\n"),
18376 };
Douglas Creager134b52e2018-11-09 18:00:1418377 MockRead data_reads[] = {
18378 MockRead("HTTP/1.0 200 OK\r\n"),
18379 MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
18380 "\"endpoints\": [{\"url\": "
18381 "\"https://www.example.org/upload/\"}]}\r\n"),
18382 MockRead("\r\n"),
18383 MockRead("hello world"),
18384 MockRead(SYNCHRONOUS, OK),
18385 };
Douglas Creager134b52e2018-11-09 18:00:1418386
Lily Chenfec60d92019-01-24 01:16:4218387 StaticSocketDataProvider reads(data_reads, data_writes);
18388 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager134b52e2018-11-09 18:00:1418389
18390 SSLSocketDataProvider ssl(ASYNC, OK);
18391 if (request.url.SchemeIsCryptographic()) {
18392 ssl.ssl_info.cert =
18393 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18394 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218395 ssl.ssl_info.cert_status = cert_status;
Douglas Creager134b52e2018-11-09 18:00:1418396 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18397 }
18398
Douglas Creager134b52e2018-11-09 18:00:1418399 TestCompletionCallback callback;
18400 auto session = CreateSession(&session_deps_);
18401 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18402 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
Lily Chenfec60d92019-01-24 01:16:4218403 EXPECT_THAT(callback.GetResult(rv), IsOk());
Douglas Creager134b52e2018-11-09 18:00:1418404 }
18405
18406 protected:
18407 std::string url_ = "https://www.example.org/";
Douglas Creager134b52e2018-11-09 18:00:1418408
18409 private:
18410 TestReportingContext* test_reporting_context_;
18411};
18412
18413TEST_F(HttpNetworkTransactionReportingTest,
18414 DontProcessReportToHeaderNoService) {
18415 base::HistogramTester histograms;
18416 clear_reporting_service();
18417 RequestPolicy();
18418 histograms.ExpectBucketCount(
18419 ReportingHeaderParser::kHeaderOutcomeHistogram,
18420 ReportingHeaderParser::HeaderOutcome::DISCARDED_NO_REPORTING_SERVICE, 1);
18421}
18422
18423TEST_F(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
18424 base::HistogramTester histograms;
18425 url_ = "http://www.example.org/";
18426 RequestPolicy();
18427 histograms.ExpectBucketCount(
18428 ReportingHeaderParser::kHeaderOutcomeHistogram,
18429 ReportingHeaderParser::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18430}
18431
18432TEST_F(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
18433 RequestPolicy();
Lily Chenefb6fcf2019-04-19 04:17:5418434 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
Lily Chenfc92ff42019-05-06 22:59:1018435 const ReportingEndpoint endpoint =
Lily Chenefb6fcf2019-04-19 04:17:5418436 reporting_context()->cache()->GetEndpointForTesting(
18437 url::Origin::Create(GURL("https://www.example.org/")), "nel",
18438 GURL("https://www.example.org/upload/"));
18439 EXPECT_TRUE(endpoint);
Douglas Creager134b52e2018-11-09 18:00:1418440}
18441
18442TEST_F(HttpNetworkTransactionReportingTest,
18443 DontProcessReportToHeaderInvalidHttps) {
18444 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218445 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18446 RequestPolicy(cert_status);
Douglas Creager134b52e2018-11-09 18:00:1418447 histograms.ExpectBucketCount(
18448 ReportingHeaderParser::kHeaderOutcomeHistogram,
18449 ReportingHeaderParser::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR, 1);
18450}
18451#endif // BUILDFLAG(ENABLE_REPORTING)
18452
18453//-----------------------------------------------------------------------------
Douglas Creager3cb042052018-11-06 23:08:5218454// Network Error Logging tests
18455
18456#if BUILDFLAG(ENABLE_REPORTING)
Lily Chenfec60d92019-01-24 01:16:4218457namespace {
18458
18459const char kUserAgent[] = "Mozilla/1.0";
18460const char kReferrer[] = "https://www.referrer.org/";
18461
18462} // namespace
18463
Douglas Creager3cb042052018-11-06 23:08:5218464class HttpNetworkTransactionNetworkErrorLoggingTest
18465 : public HttpNetworkTransactionTest {
18466 protected:
18467 void SetUp() override {
Douglas Creageref5eecdc2018-11-09 20:50:3618468 HttpNetworkTransactionTest::SetUp();
Douglas Creager3cb042052018-11-06 23:08:5218469 auto network_error_logging_service =
18470 std::make_unique<TestNetworkErrorLoggingService>();
18471 test_network_error_logging_service_ = network_error_logging_service.get();
18472 session_deps_.network_error_logging_service =
18473 std::move(network_error_logging_service);
Lily Chenfec60d92019-01-24 01:16:4218474
18475 extra_headers_.SetHeader("User-Agent", kUserAgent);
18476 extra_headers_.SetHeader("Referer", kReferrer);
18477
18478 request_.method = "GET";
18479 request_.url = GURL(url_);
18480 request_.extra_headers = extra_headers_;
18481 request_.reporting_upload_depth = reporting_upload_depth_;
18482 request_.traffic_annotation =
18483 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
Douglas Creager3cb042052018-11-06 23:08:5218484 }
18485
18486 TestNetworkErrorLoggingService* network_error_logging_service() const {
18487 return test_network_error_logging_service_;
18488 }
18489
18490 void clear_network_error_logging_service() {
18491 session_deps_.network_error_logging_service.reset();
18492 test_network_error_logging_service_ = nullptr;
18493 }
18494
18495 // Makes an HTTPS request that should install a valid NEL policy.
Lily Chenfec60d92019-01-24 01:16:4218496 void RequestPolicy(CertStatus cert_status = 0) {
Douglas Creageref5eecdc2018-11-09 20:50:3618497 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318498 MockWrite data_writes[] = {
18499 MockWrite("GET / HTTP/1.1\r\n"
18500 "Host: www.example.org\r\n"
18501 "Connection: keep-alive\r\n"),
18502 MockWrite(ASYNC, extra_header_string.data(),
18503 extra_header_string.size()),
18504 };
Lily Chend3930e72019-03-01 19:31:1118505 MockRead data_reads[] = {
18506 MockRead("HTTP/1.0 200 OK\r\n"),
18507 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18508 MockRead("\r\n"),
18509 MockRead("hello world"),
18510 MockRead(SYNCHRONOUS, OK),
18511 };
Douglas Creager3cb042052018-11-06 23:08:5218512
Lily Chenfec60d92019-01-24 01:16:4218513 StaticSocketDataProvider reads(data_reads, data_writes);
18514 session_deps_.socket_factory->AddSocketDataProvider(&reads);
Douglas Creager3cb042052018-11-06 23:08:5218515
18516 SSLSocketDataProvider ssl(ASYNC, OK);
Lily Chenfec60d92019-01-24 01:16:4218517 if (request_.url.SchemeIsCryptographic()) {
Douglas Creager3cb042052018-11-06 23:08:5218518 ssl.ssl_info.cert =
18519 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18520 ASSERT_TRUE(ssl.ssl_info.cert);
Lily Chenfec60d92019-01-24 01:16:4218521 ssl.ssl_info.cert_status = cert_status;
Douglas Creager3cb042052018-11-06 23:08:5218522 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18523 }
18524
Douglas Creager3cb042052018-11-06 23:08:5218525 TestCompletionCallback callback;
18526 auto session = CreateSession(&session_deps_);
18527 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
Lily Chenfec60d92019-01-24 01:16:4218528 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
18529 EXPECT_THAT(callback.GetResult(rv), IsOk());
18530
18531 std::string response_data;
18532 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18533 EXPECT_EQ("hello world", response_data);
18534 }
18535
18536 void CheckReport(size_t index,
18537 int status_code,
18538 int error_type,
18539 IPAddress server_ip = IPAddress::IPv4Localhost()) {
18540 ASSERT_LT(index, network_error_logging_service()->errors().size());
18541
18542 const NetworkErrorLoggingService::RequestDetails& error =
18543 network_error_logging_service()->errors()[index];
18544 EXPECT_EQ(url_, error.uri);
18545 EXPECT_EQ(kReferrer, error.referrer);
18546 EXPECT_EQ(kUserAgent, error.user_agent);
18547 EXPECT_EQ(server_ip, error.server_ip);
18548 EXPECT_EQ("http/1.1", error.protocol);
18549 EXPECT_EQ("GET", error.method);
18550 EXPECT_EQ(status_code, error.status_code);
18551 EXPECT_EQ(error_type, error.type);
18552 EXPECT_EQ(0, error.reporting_upload_depth);
Douglas Creager3cb042052018-11-06 23:08:5218553 }
18554
18555 protected:
18556 std::string url_ = "https://www.example.org/";
18557 CertStatus cert_status_ = 0;
Lily Chenfec60d92019-01-24 01:16:4218558 HttpRequestInfo request_;
Douglas Creageref5eecdc2018-11-09 20:50:3618559 HttpRequestHeaders extra_headers_;
18560 int reporting_upload_depth_ = 0;
Douglas Creager3cb042052018-11-06 23:08:5218561
18562 private:
18563 TestNetworkErrorLoggingService* test_network_error_logging_service_;
18564};
18565
18566TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18567 DontProcessNelHeaderNoService) {
18568 base::HistogramTester histograms;
18569 clear_network_error_logging_service();
18570 RequestPolicy();
18571 histograms.ExpectBucketCount(
18572 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18573 NetworkErrorLoggingService::HeaderOutcome::
18574 DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE,
18575 1);
18576}
18577
18578TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18579 DontProcessNelHeaderHttp) {
18580 base::HistogramTester histograms;
18581 url_ = "http://www.example.org/";
Lily Chenfec60d92019-01-24 01:16:4218582 request_.url = GURL(url_);
Douglas Creager3cb042052018-11-06 23:08:5218583 RequestPolicy();
18584 histograms.ExpectBucketCount(
18585 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18586 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_INVALID_SSL_INFO, 1);
18587}
18588
Lily Chen90ae93cc2019-02-14 01:15:3918589// Don't set NEL policies received on a proxied connection.
18590TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18591 DontProcessNelHeaderProxy) {
18592 session_deps_.proxy_resolution_service =
18593 ProxyResolutionService::CreateFixedFromPacResult(
18594 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
18595 BoundTestNetLog log;
18596 session_deps_.net_log = log.bound().net_log();
18597 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18598
18599 HttpRequestInfo request;
18600 request.method = "GET";
18601 request.url = GURL("https://www.example.org/");
18602 request.traffic_annotation =
18603 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18604
18605 // Since we have proxy, should try to establish tunnel.
18606 MockWrite data_writes1[] = {
18607 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
18608 "Host: www.example.org:443\r\n"
18609 "Proxy-Connection: keep-alive\r\n\r\n"),
18610
18611 MockWrite("GET / HTTP/1.1\r\n"
18612 "Host: www.example.org\r\n"
18613 "Connection: keep-alive\r\n\r\n"),
18614 };
18615
18616 MockRead data_reads1[] = {
18617 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
18618
18619 MockRead("HTTP/1.1 200 OK\r\n"),
18620 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
18621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18622 MockRead("Content-Length: 100\r\n\r\n"),
18623 MockRead(SYNCHRONOUS, OK),
18624 };
18625
18626 StaticSocketDataProvider data1(data_reads1, data_writes1);
18627 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18628 SSLSocketDataProvider ssl(ASYNC, OK);
18629 ssl.ssl_info.cert =
18630 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
18631 ASSERT_TRUE(ssl.ssl_info.cert);
18632 ssl.ssl_info.cert_status = 0;
18633 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18634
18635 TestCompletionCallback callback1;
18636 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18637
18638 int rv = trans.Start(&request, callback1.callback(), log.bound());
18639 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18640
18641 rv = callback1.WaitForResult();
18642 EXPECT_THAT(rv, IsOk());
18643
18644 const HttpResponseInfo* response = trans.GetResponseInfo();
18645 ASSERT_TRUE(response);
18646 EXPECT_EQ(200, response->headers->response_code());
18647 EXPECT_TRUE(response->was_fetched_via_proxy);
18648
18649 // No NEL header was set.
18650 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
18651}
18652
Douglas Creager3cb042052018-11-06 23:08:5218653TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
18654 RequestPolicy();
18655 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
18656 const auto& header = network_error_logging_service()->headers()[0];
18657 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
18658 header.origin);
18659 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
18660 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
18661}
18662
18663TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18664 DontProcessNelHeaderInvalidHttps) {
18665 base::HistogramTester histograms;
Lily Chenfec60d92019-01-24 01:16:4218666 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
18667 RequestPolicy(cert_status);
Douglas Creager3cb042052018-11-06 23:08:5218668 histograms.ExpectBucketCount(
18669 NetworkErrorLoggingService::kHeaderOutcomeHistogram,
18670 NetworkErrorLoggingService::HeaderOutcome::DISCARDED_CERT_STATUS_ERROR,
18671 1);
18672}
Douglas Creageref5eecdc2018-11-09 20:50:3618673
Lily Chenfec60d92019-01-24 01:16:4218674TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
Douglas Creageref5eecdc2018-11-09 20:50:3618675 RequestPolicy();
18676 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4218677 CheckReport(0 /* index */, 200 /* status_code */, OK);
18678}
18679
18680TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18681 CreateReportErrorAfterStart) {
18682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18683 auto trans =
18684 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18685
18686 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
18687 StaticSocketDataProvider data;
18688 data.set_connect_data(mock_connect);
18689 session_deps_.socket_factory->AddSocketDataProvider(&data);
18690
18691 TestCompletionCallback callback;
18692
18693 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18694 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18695
18696 trans.reset();
18697
18698 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18699 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18700 IPAddress() /* server_ip */);
18701}
18702
18703// Same as above except the error is ASYNC
18704TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18705 CreateReportErrorAfterStartAsync) {
18706 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18707 auto trans =
18708 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18709
18710 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
18711 StaticSocketDataProvider data;
18712 data.set_connect_data(mock_connect);
18713 session_deps_.socket_factory->AddSocketDataProvider(&data);
18714
18715 TestCompletionCallback callback;
18716
18717 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18718 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
18719
18720 trans.reset();
18721
18722 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18723 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
18724 IPAddress() /* server_ip */);
18725}
18726
18727TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18728 CreateReportReadBodyError) {
18729 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318730 MockWrite data_writes[] = {
18731 MockWrite("GET / HTTP/1.1\r\n"
18732 "Host: www.example.org\r\n"
18733 "Connection: keep-alive\r\n"),
18734 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18735 };
Lily Chend3930e72019-03-01 19:31:1118736 MockRead data_reads[] = {
18737 MockRead("HTTP/1.0 200 OK\r\n"),
18738 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18739 MockRead("hello world"),
18740 MockRead(SYNCHRONOUS, OK),
18741 };
Lily Chenfec60d92019-01-24 01:16:4218742
18743 StaticSocketDataProvider reads(data_reads, data_writes);
18744 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18745
18746 SSLSocketDataProvider ssl(ASYNC, OK);
18747 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18748
18749 // Log start time
18750 base::TimeTicks start_time = base::TimeTicks::Now();
18751
18752 TestCompletionCallback callback;
18753 auto session = CreateSession(&session_deps_);
18754 auto trans =
18755 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18756 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18757 EXPECT_THAT(callback.GetResult(rv), IsOk());
18758
18759 const HttpResponseInfo* response = trans->GetResponseInfo();
18760 ASSERT_TRUE(response);
18761
18762 EXPECT_TRUE(response->headers);
18763 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18764
18765 std::string response_data;
18766 rv = ReadTransaction(trans.get(), &response_data);
18767 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18768
18769 trans.reset();
18770
18771 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18772
18773 CheckReport(0 /* index */, 200 /* status_code */,
18774 ERR_CONTENT_LENGTH_MISMATCH);
18775 const NetworkErrorLoggingService::RequestDetails& error =
18776 network_error_logging_service()->errors()[0];
18777 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18778}
18779
18780// Same as above except the final read is ASYNC.
18781TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18782 CreateReportReadBodyErrorAsync) {
18783 std::string extra_header_string = extra_headers_.ToString();
Lily Chen29c04032019-02-25 21:50:5318784 MockWrite data_writes[] = {
18785 MockWrite("GET / HTTP/1.1\r\n"
18786 "Host: www.example.org\r\n"
18787 "Connection: keep-alive\r\n"),
18788 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18789 };
Lily Chend3930e72019-03-01 19:31:1118790 MockRead data_reads[] = {
18791 MockRead("HTTP/1.0 200 OK\r\n"),
18792 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
18793 MockRead("hello world"),
18794 MockRead(ASYNC, OK),
18795 };
Lily Chenfec60d92019-01-24 01:16:4218796
18797 StaticSocketDataProvider reads(data_reads, data_writes);
18798 session_deps_.socket_factory->AddSocketDataProvider(&reads);
18799
18800 SSLSocketDataProvider ssl(ASYNC, OK);
18801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18802
18803 // Log start time
18804 base::TimeTicks start_time = base::TimeTicks::Now();
18805
18806 TestCompletionCallback callback;
18807 auto session = CreateSession(&session_deps_);
18808 auto trans =
18809 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18810 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
18811 EXPECT_THAT(callback.GetResult(rv), IsOk());
18812
18813 const HttpResponseInfo* response = trans->GetResponseInfo();
18814 ASSERT_TRUE(response);
18815
18816 EXPECT_TRUE(response->headers);
18817 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
18818
18819 std::string response_data;
18820 rv = ReadTransaction(trans.get(), &response_data);
18821 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
18822
18823 trans.reset();
18824
18825 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18826
18827 CheckReport(0 /* index */, 200 /* status_code */,
18828 ERR_CONTENT_LENGTH_MISMATCH);
18829 const NetworkErrorLoggingService::RequestDetails& error =
18830 network_error_logging_service()->errors()[0];
18831 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
18832}
18833
18834TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18835 CreateReportRestartWithAuth) {
18836 std::string extra_header_string = extra_headers_.ToString();
18837 static const base::TimeDelta kSleepDuration =
18838 base::TimeDelta::FromMilliseconds(10);
18839
18840 MockWrite data_writes1[] = {
18841 MockWrite("GET / HTTP/1.1\r\n"
18842 "Host: www.example.org\r\n"
18843 "Connection: keep-alive\r\n"),
18844 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18845 };
18846
18847 MockRead data_reads1[] = {
18848 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
18849 // Give a couple authenticate options (only the middle one is actually
18850 // supported).
18851 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
18852 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
18853 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
18854 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18855 // Large content-length -- won't matter, as connection will be reset.
18856 MockRead("Content-Length: 10000\r\n\r\n"),
18857 MockRead(SYNCHRONOUS, ERR_FAILED),
18858 };
18859
18860 // After calling trans->RestartWithAuth(), this is the request we should
18861 // be issuing -- the final header line contains the credentials.
18862 MockWrite data_writes2[] = {
18863 MockWrite("GET / HTTP/1.1\r\n"
18864 "Host: www.example.org\r\n"
18865 "Connection: keep-alive\r\n"
18866 "Authorization: Basic Zm9vOmJhcg==\r\n"),
18867 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18868 };
18869
18870 // Lastly, the server responds with the actual content.
18871 MockRead data_reads2[] = {
18872 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
18873 MockRead("hello world"),
18874 MockRead(SYNCHRONOUS, OK),
18875 };
18876
18877 StaticSocketDataProvider data1(data_reads1, data_writes1);
18878 StaticSocketDataProvider data2(data_reads2, data_writes2);
18879 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18880 session_deps_.socket_factory->AddSocketDataProvider(&data2);
18881
18882 SSLSocketDataProvider ssl1(ASYNC, OK);
18883 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18884 SSLSocketDataProvider ssl2(ASYNC, OK);
18885 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18886
18887 base::TimeTicks start_time = base::TimeTicks::Now();
18888 base::TimeTicks restart_time;
18889
18890 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18891 auto trans =
18892 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18893
18894 TestCompletionCallback callback1;
18895
18896 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
18897 EXPECT_THAT(callback1.GetResult(rv), IsOk());
18898
18899 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
18900
18901 TestCompletionCallback callback2;
18902
18903 // Wait 10 ms then restart with auth
18904 FastForwardBy(kSleepDuration);
18905 restart_time = base::TimeTicks::Now();
18906 rv =
18907 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
18908 EXPECT_THAT(callback2.GetResult(rv), IsOk());
18909
18910 std::string response_data;
18911 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
18912 EXPECT_EQ("hello world", response_data);
18913
18914 trans.reset();
18915
18916 // One 401 report for the auth challenge, then a 200 report for the successful
18917 // retry. Note that we don't report the error draining the body, as the first
18918 // request already generated a report for the auth challenge.
18919 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
18920
18921 // Check error report contents
18922 CheckReport(0 /* index */, 401 /* status_code */, OK);
18923 CheckReport(1 /* index */, 200 /* status_code */, OK);
18924
18925 const NetworkErrorLoggingService::RequestDetails& error1 =
18926 network_error_logging_service()->errors()[0];
18927 const NetworkErrorLoggingService::RequestDetails& error2 =
18928 network_error_logging_service()->errors()[1];
18929
18930 // Sanity-check elapsed time values
18931 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
18932 // Check that the start time is refreshed when restarting with auth.
18933 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
18934}
18935
18936// Same as above, except draining the body before restarting fails
18937// asynchronously.
18938TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
18939 CreateReportRestartWithAuthAsync) {
18940 std::string extra_header_string = extra_headers_.ToString();
18941 static const base::TimeDelta kSleepDuration =
18942 base::TimeDelta::FromMilliseconds(10);
18943
18944 MockWrite data_writes1[] = {
18945 MockWrite("GET / HTTP/1.1\r\n"
18946 "Host: www.example.org\r\n"
18947 "Connection: keep-alive\r\n"),
18948 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18949 };
18950
18951 MockRead data_reads1[] = {
18952 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
18953 // Give a couple authenticate options (only the middle one is actually
18954 // supported).
18955 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
18956 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
18957 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
18958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
18959 // Large content-length -- won't matter, as connection will be reset.
18960 MockRead("Content-Length: 10000\r\n\r\n"),
18961 MockRead(ASYNC, ERR_FAILED),
18962 };
18963
18964 // After calling trans->RestartWithAuth(), this is the request we should
18965 // be issuing -- the final header line contains the credentials.
18966 MockWrite data_writes2[] = {
18967 MockWrite("GET / HTTP/1.1\r\n"
18968 "Host: www.example.org\r\n"
18969 "Connection: keep-alive\r\n"
18970 "Authorization: Basic Zm9vOmJhcg==\r\n"),
18971 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
18972 };
18973
18974 // Lastly, the server responds with the actual content.
18975 MockRead data_reads2[] = {
18976 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
18977 MockRead("hello world"),
18978 MockRead(SYNCHRONOUS, OK),
18979 };
18980
18981 StaticSocketDataProvider data1(data_reads1, data_writes1);
18982 StaticSocketDataProvider data2(data_reads2, data_writes2);
18983 session_deps_.socket_factory->AddSocketDataProvider(&data1);
18984 session_deps_.socket_factory->AddSocketDataProvider(&data2);
18985
18986 SSLSocketDataProvider ssl1(ASYNC, OK);
18987 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
18988 SSLSocketDataProvider ssl2(ASYNC, OK);
18989 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
18990
18991 base::TimeTicks start_time = base::TimeTicks::Now();
18992 base::TimeTicks restart_time;
18993
18994 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18995 auto trans =
18996 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
18997
18998 TestCompletionCallback callback1;
18999
19000 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
19001 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19002
19003 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19004
19005 TestCompletionCallback callback2;
19006
19007 // Wait 10 ms then restart with auth
19008 FastForwardBy(kSleepDuration);
19009 restart_time = base::TimeTicks::Now();
19010 rv =
19011 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19012 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19013
19014 std::string response_data;
19015 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19016 EXPECT_EQ("hello world", response_data);
19017
19018 trans.reset();
19019
19020 // One 401 report for the auth challenge, then a 200 report for the successful
19021 // retry. Note that we don't report the error draining the body, as the first
19022 // request already generated a report for the auth challenge.
19023 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
19024
19025 // Check error report contents
19026 CheckReport(0 /* index */, 401 /* status_code */, OK);
19027 CheckReport(1 /* index */, 200 /* status_code */, OK);
19028
19029 const NetworkErrorLoggingService::RequestDetails& error1 =
19030 network_error_logging_service()->errors()[0];
19031 const NetworkErrorLoggingService::RequestDetails& error2 =
19032 network_error_logging_service()->errors()[1];
19033
19034 // Sanity-check elapsed time values
19035 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
19036 // Check that the start time is refreshed when restarting with auth.
19037 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
19038}
19039
19040TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19041 CreateReportRetryKeepAliveConnectionReset) {
19042 std::string extra_header_string = extra_headers_.ToString();
19043 MockWrite data_writes1[] = {
19044 MockWrite("GET / HTTP/1.1\r\n"
19045 "Host: www.example.org\r\n"
19046 "Connection: keep-alive\r\n"),
19047 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19048 MockWrite("GET / HTTP/1.1\r\n"
19049 "Host: www.example.org\r\n"
19050 "Connection: keep-alive\r\n"),
19051 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19052 };
19053
19054 MockRead data_reads1[] = {
19055 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19056 MockRead("hello"),
19057 // Connection is reset
19058 MockRead(ASYNC, ERR_CONNECTION_RESET),
19059 };
19060
19061 // Successful retry
19062 MockRead data_reads2[] = {
19063 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19064 MockRead("world"),
19065 MockRead(ASYNC, OK),
19066 };
19067
19068 StaticSocketDataProvider data1(data_reads1, data_writes1);
19069 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19070 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19071 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19072
19073 SSLSocketDataProvider ssl1(ASYNC, OK);
19074 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19075 SSLSocketDataProvider ssl2(ASYNC, OK);
19076 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19077
19078 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19079 auto trans1 =
19080 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19081
19082 TestCompletionCallback callback1;
19083
19084 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19085 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19086
19087 std::string response_data;
19088 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19089 EXPECT_EQ("hello", response_data);
19090
19091 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19092
19093 auto trans2 =
19094 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19095
19096 TestCompletionCallback callback2;
19097
19098 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19099 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19100
19101 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19102 EXPECT_EQ("world", response_data);
19103
19104 trans1.reset();
19105 trans2.reset();
19106
19107 // One OK report from first request, then a ERR_CONNECTION_RESET report from
19108 // the second request, then an OK report from the successful retry.
19109 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19110
19111 // Check error report contents
19112 CheckReport(0 /* index */, 200 /* status_code */, OK);
19113 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
19114 CheckReport(2 /* index */, 200 /* status_code */, OK);
19115}
19116
19117TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19118 CreateReportRetryKeepAlive408) {
19119 std::string extra_header_string = extra_headers_.ToString();
19120 MockWrite data_writes1[] = {
19121 MockWrite("GET / HTTP/1.1\r\n"
19122 "Host: www.example.org\r\n"
19123 "Connection: keep-alive\r\n"),
19124 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19125 MockWrite("GET / HTTP/1.1\r\n"
19126 "Host: www.example.org\r\n"
19127 "Connection: keep-alive\r\n"),
19128 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19129 };
19130
19131 MockRead data_reads1[] = {
19132 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19133 MockRead("hello"),
19134 // 408 Request Timeout
19135 MockRead(SYNCHRONOUS,
19136 "HTTP/1.1 408 Request Timeout\r\n"
19137 "Connection: Keep-Alive\r\n"
19138 "Content-Length: 6\r\n\r\n"
19139 "Pickle"),
19140 };
19141
19142 // Successful retry
19143 MockRead data_reads2[] = {
19144 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
19145 MockRead("world"),
19146 MockRead(ASYNC, OK),
19147 };
19148
19149 StaticSocketDataProvider data1(data_reads1, data_writes1);
19150 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
19151 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19152 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19153
19154 SSLSocketDataProvider ssl1(ASYNC, OK);
19155 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
19156 SSLSocketDataProvider ssl2(ASYNC, OK);
19157 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
19158
19159 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19160 auto trans1 =
19161 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19162
19163 TestCompletionCallback callback1;
19164
19165 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
19166 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19167
19168 std::string response_data;
19169 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19170 EXPECT_EQ("hello", response_data);
19171
19172 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19173
19174 auto trans2 =
19175 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19176
19177 TestCompletionCallback callback2;
19178
19179 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
19180 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19181
19182 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19183 EXPECT_EQ("world", response_data);
19184
19185 trans1.reset();
19186 trans2.reset();
19187
19188 // One 200 report from first request, then a 408 report from
19189 // the second request, then a 200 report from the successful retry.
19190 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19191
19192 // Check error report contents
19193 CheckReport(0 /* index */, 200 /* status_code */, OK);
19194 CheckReport(1 /* index */, 408 /* status_code */, OK);
19195 CheckReport(2 /* index */, 200 /* status_code */, OK);
19196}
19197
19198TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19199 CreateReportRetry421WithoutConnectionPooling) {
19200 // Two hosts resolve to the same IP address.
19201 const std::string ip_addr = "1.2.3.4";
19202 IPAddress ip;
19203 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
19204 IPEndPoint peer_addr = IPEndPoint(ip, 443);
19205
19206 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19207 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
19208 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
19209
19210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19211
19212 // Two requests on the first connection.
19213 spdy::SpdySerializedFrame req1(
19214 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19215 spdy_util_.UpdateWithStreamDestruction(1);
19216 spdy::SpdySerializedFrame req2(
19217 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
19218 spdy::SpdySerializedFrame rst(
19219 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
19220 MockWrite writes1[] = {
19221 CreateMockWrite(req1, 0),
19222 CreateMockWrite(req2, 3),
19223 CreateMockWrite(rst, 6),
19224 };
19225
19226 // The first one succeeds, the second gets error 421 Misdirected Request.
19227 spdy::SpdySerializedFrame resp1(
19228 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19229 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
19230 spdy::SpdyHeaderBlock response_headers;
19231 response_headers[spdy::kHttp2StatusHeader] = "421";
19232 spdy::SpdySerializedFrame resp2(
19233 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
19234 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
19235 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
19236
19237 MockConnect connect1(ASYNC, OK, peer_addr);
19238 SequencedSocketData data1(connect1, reads1, writes1);
19239 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19240
19241 AddSSLSocketData();
19242
19243 // Retry the second request on a second connection.
19244 SpdyTestUtil spdy_util2;
19245 spdy::SpdySerializedFrame req3(
19246 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
19247 MockWrite writes2[] = {
19248 CreateMockWrite(req3, 0),
19249 };
19250
19251 spdy::SpdySerializedFrame resp3(
19252 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
19253 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
19254 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
19255 MockRead(ASYNC, 0, 3)};
19256
19257 MockConnect connect2(ASYNC, OK, peer_addr);
19258 SequencedSocketData data2(connect2, reads2, writes2);
19259 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19260
19261 AddSSLSocketData();
19262
19263 // Preload mail.example.org into HostCache.
Eric Orthf4db66a2019-02-19 21:35:3319264 int rv = session_deps_.host_resolver->LoadIntoCache(
19265 HostPortPair("mail.example.com", 443), base::nullopt);
19266 EXPECT_THAT(rv, IsOk());
Lily Chenfec60d92019-01-24 01:16:4219267
19268 HttpRequestInfo request1;
19269 request1.method = "GET";
19270 request1.url = GURL("https://www.example.org/");
19271 request1.load_flags = 0;
19272 request1.traffic_annotation =
19273 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19274 auto trans1 =
19275 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19276
Eric Orthf4db66a2019-02-19 21:35:3319277 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219278 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
19279 EXPECT_THAT(callback.GetResult(rv), IsOk());
19280
19281 const HttpResponseInfo* response = trans1->GetResponseInfo();
19282 ASSERT_TRUE(response);
19283 ASSERT_TRUE(response->headers);
19284 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19285 EXPECT_TRUE(response->was_fetched_via_spdy);
19286 EXPECT_TRUE(response->was_alpn_negotiated);
19287 std::string response_data;
19288 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
19289 EXPECT_EQ("hello!", response_data);
19290
19291 trans1.reset();
19292
19293 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19294
19295 HttpRequestInfo request2;
19296 request2.method = "GET";
19297 request2.url = GURL("https://mail.example.org/");
19298 request2.load_flags = 0;
19299 request2.traffic_annotation =
19300 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19301 auto trans2 =
19302 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19303
19304 BoundTestNetLog log;
19305 rv = trans2->Start(&request2, callback.callback(), log.bound());
19306 EXPECT_THAT(callback.GetResult(rv), IsOk());
19307
19308 response = trans2->GetResponseInfo();
19309 ASSERT_TRUE(response);
19310 ASSERT_TRUE(response->headers);
19311 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19312 EXPECT_TRUE(response->was_fetched_via_spdy);
19313 EXPECT_TRUE(response->was_alpn_negotiated);
19314 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
19315 EXPECT_EQ("hello!", response_data);
19316
19317 trans2.reset();
19318
19319 // One 200 report from the first request, then a 421 report from the
19320 // second request, then a 200 report from the successful retry.
19321 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
19322
19323 // Check error report contents
19324 const NetworkErrorLoggingService::RequestDetails& error1 =
19325 network_error_logging_service()->errors()[0];
19326 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
19327 EXPECT_TRUE(error1.referrer.is_empty());
19328 EXPECT_EQ("", error1.user_agent);
19329 EXPECT_EQ(ip, error1.server_ip);
19330 EXPECT_EQ("h2", error1.protocol);
19331 EXPECT_EQ("GET", error1.method);
19332 EXPECT_EQ(200, error1.status_code);
19333 EXPECT_EQ(OK, error1.type);
19334 EXPECT_EQ(0, error1.reporting_upload_depth);
19335
19336 const NetworkErrorLoggingService::RequestDetails& error2 =
19337 network_error_logging_service()->errors()[1];
19338 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
19339 EXPECT_TRUE(error2.referrer.is_empty());
19340 EXPECT_EQ("", error2.user_agent);
19341 EXPECT_EQ(ip, error2.server_ip);
19342 EXPECT_EQ("h2", error2.protocol);
19343 EXPECT_EQ("GET", error2.method);
19344 EXPECT_EQ(421, error2.status_code);
19345 EXPECT_EQ(OK, error2.type);
19346 EXPECT_EQ(0, error2.reporting_upload_depth);
19347
19348 const NetworkErrorLoggingService::RequestDetails& error3 =
19349 network_error_logging_service()->errors()[2];
19350 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
19351 EXPECT_TRUE(error3.referrer.is_empty());
19352 EXPECT_EQ("", error3.user_agent);
19353 EXPECT_EQ(ip, error3.server_ip);
19354 EXPECT_EQ("h2", error3.protocol);
19355 EXPECT_EQ("GET", error3.method);
19356 EXPECT_EQ(200, error3.status_code);
19357 EXPECT_EQ(OK, error3.type);
19358 EXPECT_EQ(0, error3.reporting_upload_depth);
Douglas Creageref5eecdc2018-11-09 20:50:3619359}
19360
Lily Chend3930e72019-03-01 19:31:1119361TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19362 CreateReportCancelAfterStart) {
19363 StaticSocketDataProvider data;
19364 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
19365 session_deps_.socket_factory->AddSocketDataProvider(&data);
19366
19367 TestCompletionCallback callback;
19368 auto session = CreateSession(&session_deps_);
19369 auto trans =
19370 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19371 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19372 EXPECT_EQ(rv, ERR_IO_PENDING);
19373
19374 // Cancel after start.
19375 trans.reset();
19376
19377 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19378 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
19379 IPAddress() /* server_ip */);
19380}
19381
19382TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19383 CreateReportCancelBeforeReadingBody) {
19384 std::string extra_header_string = extra_headers_.ToString();
19385 MockWrite data_writes[] = {
19386 MockWrite("GET / HTTP/1.1\r\n"
19387 "Host: www.example.org\r\n"
19388 "Connection: keep-alive\r\n"),
19389 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19390 };
19391 MockRead data_reads[] = {
19392 MockRead("HTTP/1.0 200 OK\r\n"),
19393 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
19394 };
19395
19396 StaticSocketDataProvider data(data_reads, data_writes);
19397 session_deps_.socket_factory->AddSocketDataProvider(&data);
19398
19399 SSLSocketDataProvider ssl(ASYNC, OK);
19400 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19401
19402 TestCompletionCallback callback;
19403 auto session = CreateSession(&session_deps_);
19404 auto trans =
19405 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19406 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19407 EXPECT_THAT(callback.GetResult(rv), IsOk());
19408
19409 const HttpResponseInfo* response = trans->GetResponseInfo();
19410 ASSERT_TRUE(response);
19411
19412 EXPECT_TRUE(response->headers);
19413 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
19414
19415 // Cancel before reading the body.
19416 trans.reset();
19417
19418 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
19419 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
19420}
19421
Lily Chen00196ab62018-12-04 19:52:2919422TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
19423 base::HistogramTester histograms;
19424 RequestPolicy();
19425 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19426 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19427
19428 // Make HTTP request
19429 std::string extra_header_string = extra_headers_.ToString();
19430 MockRead data_reads[] = {
19431 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
19432 MockRead("hello world"),
19433 MockRead(SYNCHRONOUS, OK),
19434 };
19435 MockWrite data_writes[] = {
19436 MockWrite("GET / HTTP/1.1\r\n"
19437 "Host: www.example.org\r\n"
19438 "Connection: keep-alive\r\n"),
19439 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
19440 };
19441
Lily Chend3930e72019-03-01 19:31:1119442 StaticSocketDataProvider data(data_reads, data_writes);
19443 session_deps_.socket_factory->AddSocketDataProvider(&data);
Lily Chen00196ab62018-12-04 19:52:2919444
Lily Chenfec60d92019-01-24 01:16:4219445 // Insecure url
19446 url_ = "http://www.example.org/";
19447 request_.url = GURL(url_);
19448
Lily Chen00196ab62018-12-04 19:52:2919449 TestCompletionCallback callback;
19450 auto session = CreateSession(&session_deps_);
Lily Chenfec60d92019-01-24 01:16:4219451 auto trans =
19452 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19453 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19454 EXPECT_THAT(callback.GetResult(rv), IsOk());
19455
19456 std::string response_data;
19457 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19458 EXPECT_EQ("hello world", response_data);
Lily Chen00196ab62018-12-04 19:52:2919459
19460 // Insecure request does not generate a report
19461 histograms.ExpectBucketCount(
19462 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519463 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919464
19465 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19466}
19467
19468TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19469 DontCreateReportHttpError) {
19470 base::HistogramTester histograms;
19471 RequestPolicy();
19472 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
19473 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19474
19475 // Make HTTP request that fails
19476 MockRead data_reads[] = {
19477 MockRead("hello world"),
19478 MockRead(SYNCHRONOUS, OK),
19479 };
19480
19481 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19482 session_deps_.socket_factory->AddSocketDataProvider(&data);
19483
Lily Chenfec60d92019-01-24 01:16:4219484 url_ = "http://www.originwithoutpolicy.com:2000/";
19485 request_.url = GURL(url_);
19486
Lily Chen00196ab62018-12-04 19:52:2919487 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19488
Lily Chen00196ab62018-12-04 19:52:2919489 auto trans =
19490 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
Lily Chen00196ab62018-12-04 19:52:2919491 TestCompletionCallback callback;
Lily Chenfec60d92019-01-24 01:16:4219492 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
Lily Chen00196ab62018-12-04 19:52:2919493 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
19494
19495 // Insecure request does not generate a report, regardless of existence of a
19496 // policy for the origin.
19497 histograms.ExpectBucketCount(
19498 NetworkErrorLoggingService::kRequestOutcomeHistogram,
Tsuyoshi Horo0b042232019-03-06 01:11:0519499 NetworkErrorLoggingService::RequestOutcome::kDiscardedInsecureOrigin, 1);
Lily Chen00196ab62018-12-04 19:52:2919500
19501 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
19502}
19503
Lily Chen90ae93cc2019-02-14 01:15:3919504// Don't report on proxy auth challenges, don't report if connecting through a
19505// proxy.
19506TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
19507 HttpRequestInfo request;
19508 request.method = "GET";
19509 request.url = GURL("https://www.example.org/");
19510 request.traffic_annotation =
19511 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19512
19513 // Configure against proxy server "myproxy:70".
19514 session_deps_.proxy_resolution_service =
19515 ProxyResolutionService::CreateFixedFromPacResult(
19516 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19517 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19518
19519 // Since we have proxy, should try to establish tunnel.
19520 MockWrite data_writes1[] = {
19521 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19522 "Host: www.example.org:443\r\n"
19523 "Proxy-Connection: keep-alive\r\n\r\n"),
19524 };
19525
19526 // The proxy responds to the connect with a 407, using a non-persistent
19527 // connection.
19528 MockRead data_reads1[] = {
19529 // No credentials.
19530 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
19531 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
19532 MockRead("Proxy-Connection: close\r\n\r\n"),
19533 };
19534
19535 MockWrite data_writes2[] = {
19536 // After calling trans->RestartWithAuth(), this is the request we should
19537 // be issuing -- the final header line contains the credentials.
19538 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19539 "Host: www.example.org:443\r\n"
19540 "Proxy-Connection: keep-alive\r\n"
19541 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
19542
19543 MockWrite("GET / HTTP/1.1\r\n"
19544 "Host: www.example.org\r\n"
19545 "Connection: keep-alive\r\n\r\n"),
19546 };
19547
19548 MockRead data_reads2[] = {
19549 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19550
19551 MockRead("HTTP/1.1 200 OK\r\n"),
19552 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19553 MockRead("Content-Length: 5\r\n\r\n"),
19554 MockRead(SYNCHRONOUS, "hello"),
19555 };
19556
19557 StaticSocketDataProvider data1(data_reads1, data_writes1);
19558 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19559 StaticSocketDataProvider data2(data_reads2, data_writes2);
19560 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19561 SSLSocketDataProvider ssl(ASYNC, OK);
19562 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19563
19564 TestCompletionCallback callback1;
19565
19566 auto trans =
19567 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19568
19569 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
19570 EXPECT_THAT(callback1.GetResult(rv), IsOk());
19571
19572 const HttpResponseInfo* response = trans->GetResponseInfo();
19573 EXPECT_EQ(407, response->headers->response_code());
19574
19575 std::string response_data;
19576 rv = ReadTransaction(trans.get(), &response_data);
19577 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
19578
19579 // No NEL report is generated for the 407.
19580 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19581
19582 TestCompletionCallback callback2;
19583
19584 rv =
19585 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
19586 EXPECT_THAT(callback2.GetResult(rv), IsOk());
19587
19588 response = trans->GetResponseInfo();
19589 EXPECT_EQ(200, response->headers->response_code());
19590
19591 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19592 EXPECT_EQ("hello", response_data);
19593
19594 trans.reset();
19595
19596 // No NEL report is generated because we are behind a proxy.
19597 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
19598}
19599
Douglas Creageref5eecdc2018-11-09 20:50:3619600TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
19601 ReportContainsUploadDepth) {
19602 reporting_upload_depth_ = 7;
Lily Chenfec60d92019-01-24 01:16:4219603 request_.reporting_upload_depth = reporting_upload_depth_;
Douglas Creageref5eecdc2018-11-09 20:50:3619604 RequestPolicy();
19605 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219606 const NetworkErrorLoggingService::RequestDetails& error =
19607 network_error_logging_service()->errors()[0];
Douglas Creageref5eecdc2018-11-09 20:50:3619608 EXPECT_EQ(7, error.reporting_upload_depth);
19609}
19610
Lily Chenfec60d92019-01-24 01:16:4219611TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
19612 std::string extra_header_string = extra_headers_.ToString();
19613 static const base::TimeDelta kSleepDuration =
19614 base::TimeDelta::FromMilliseconds(10);
19615
19616 std::vector<MockWrite> data_writes = {
19617 MockWrite(ASYNC, 0,
19618 "GET / HTTP/1.1\r\n"
19619 "Host: www.example.org\r\n"
19620 "Connection: keep-alive\r\n"),
19621 MockWrite(ASYNC, 1, extra_header_string.data()),
19622 };
19623
19624 std::vector<MockRead> data_reads = {
19625 // Write one byte of the status line, followed by a pause.
19626 MockRead(ASYNC, 2, "H"),
19627 MockRead(ASYNC, ERR_IO_PENDING, 3),
19628 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
19629 MockRead(ASYNC, 5, "hello world"),
19630 MockRead(SYNCHRONOUS, OK, 6),
19631 };
19632
19633 SequencedSocketData data(data_reads, data_writes);
19634 session_deps_.socket_factory->AddSocketDataProvider(&data);
19635
19636 SSLSocketDataProvider ssl(ASYNC, OK);
19637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19638
19639 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19640
19641 auto trans =
19642 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19643
19644 TestCompletionCallback callback;
19645
19646 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
19647 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19648
19649 data.RunUntilPaused();
19650 ASSERT_TRUE(data.IsPaused());
19651 FastForwardBy(kSleepDuration);
19652 data.Resume();
19653
19654 EXPECT_THAT(callback.GetResult(rv), IsOk());
19655
19656 std::string response_data;
19657 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
19658 EXPECT_EQ("hello world", response_data);
19659
19660 trans.reset();
19661
Douglas Creageref5eecdc2018-11-09 20:50:3619662 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
Lily Chenfec60d92019-01-24 01:16:4219663
19664 CheckReport(0 /* index */, 200 /* status_code */, OK);
19665
19666 const NetworkErrorLoggingService::RequestDetails& error =
19667 network_error_logging_service()->errors()[0];
19668
19669 // Sanity-check elapsed time in error report
19670 EXPECT_EQ(kSleepDuration, error.elapsed_time);
Douglas Creageref5eecdc2018-11-09 20:50:3619671}
Lily Chenfec60d92019-01-24 01:16:4219672
Douglas Creager3cb042052018-11-06 23:08:5219673#endif // BUILDFLAG(ENABLE_REPORTING)
19674
Batalov Vladislava4e97a502019-04-11 15:35:2319675TEST_F(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
19676 HttpRequestInfo request;
19677 request.method = "GET";
19678 request.url = GURL("http://example.org/");
19679
19680 request.load_flags = LOAD_ONLY_FROM_CACHE;
19681
19682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19683 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19684 TestCompletionCallback callback1;
19685 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
19686
19687 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
19688}
19689
Steven Valdez1c1859172019-04-10 15:33:2819690TEST_F(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
19691 HttpRequestInfo request;
19692 request.method = "GET";
19693 request.url = GURL("https://www.example.org/");
19694 request.traffic_annotation =
19695 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19696
19697 MockWrite data_writes[] = {
19698 MockWrite("GET / HTTP/1.1\r\n"
19699 "Host: www.example.org\r\n"
19700 "Connection: keep-alive\r\n\r\n"),
19701 };
19702
Steven Valdez1c1859172019-04-10 15:33:2819703 MockRead data_reads[] = {
19704 MockRead("HTTP/1.1 200 OK\r\n"),
19705 MockRead("Content-Length: 1\r\n\r\n"),
19706 MockRead(SYNCHRONOUS, "1"),
19707 };
19708
19709 StaticSocketDataProvider data(data_reads, data_writes);
19710 session_deps_.socket_factory->AddSocketDataProvider(&data);
19711 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19712 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19713 session_deps_.enable_early_data = true;
19714 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19715
19716 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19717
19718 TestCompletionCallback callback;
19719 auto trans =
19720 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19721
19722 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19723 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19724
19725 rv = callback.WaitForResult();
19726 EXPECT_THAT(rv, IsOk());
19727
19728 const HttpResponseInfo* response = trans->GetResponseInfo();
19729 ASSERT_TRUE(response);
19730 ASSERT_TRUE(response->headers);
19731 EXPECT_EQ(200, response->headers->response_code());
19732 EXPECT_EQ(1, response->headers->GetContentLength());
19733
19734 // Check that ConfirmHandshake wasn't called.
19735 ASSERT_FALSE(ssl.ConfirmDataConsumed());
19736 ASSERT_TRUE(ssl.WriteBeforeConfirm());
19737
19738 trans.reset();
19739
19740 session->CloseAllConnections();
19741}
19742
19743TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
19744 HttpRequestInfo request;
19745 request.method = "POST";
19746 request.url = GURL("https://www.example.org/");
19747 request.traffic_annotation =
19748 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19749
19750 MockWrite data_writes[] = {
19751 MockWrite(SYNCHRONOUS,
19752 "POST / HTTP/1.1\r\n"
19753 "Host: www.example.org\r\n"
19754 "Connection: keep-alive\r\n"
19755 "Content-Length: 0\r\n\r\n"),
19756 };
19757
Steven Valdez1c1859172019-04-10 15:33:2819758 MockRead data_reads[] = {
19759 MockRead("HTTP/1.1 200 OK\r\n"),
19760 MockRead("Content-Length: 1\r\n\r\n"),
19761 MockRead(SYNCHRONOUS, "1"),
19762 };
19763
19764 StaticSocketDataProvider data(data_reads, data_writes);
19765 session_deps_.socket_factory->AddSocketDataProvider(&data);
19766 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19767 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19768 session_deps_.enable_early_data = true;
19769 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19770
19771 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19772
19773 TestCompletionCallback callback;
19774 auto trans =
19775 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19776
19777 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19778 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19779
19780 rv = callback.WaitForResult();
19781 EXPECT_THAT(rv, IsOk());
19782
19783 const HttpResponseInfo* response = trans->GetResponseInfo();
19784 ASSERT_TRUE(response);
19785 ASSERT_TRUE(response->headers);
19786 EXPECT_EQ(200, response->headers->response_code());
19787 EXPECT_EQ(1, response->headers->GetContentLength());
19788
19789 // Check that the Write didn't get called before ConfirmHandshake completed.
19790 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19791
19792 trans.reset();
19793
19794 session->CloseAllConnections();
19795}
19796
19797TEST_F(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
19798 HttpRequestInfo request;
19799 request.method = "POST";
19800 request.url = GURL("https://www.example.org/");
19801 request.traffic_annotation =
19802 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19803
19804 MockWrite data_writes[] = {
19805 MockWrite(ASYNC,
19806 "POST / HTTP/1.1\r\n"
19807 "Host: www.example.org\r\n"
19808 "Connection: keep-alive\r\n"
19809 "Content-Length: 0\r\n\r\n"),
19810 };
19811
Steven Valdez1c1859172019-04-10 15:33:2819812 MockRead data_reads[] = {
19813 MockRead("HTTP/1.1 200 OK\r\n"),
19814 MockRead("Content-Length: 1\r\n\r\n"),
19815 MockRead(SYNCHRONOUS, "1"),
19816 };
19817
19818 StaticSocketDataProvider data(data_reads, data_writes);
19819 session_deps_.socket_factory->AddSocketDataProvider(&data);
19820 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19821 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
19822 session_deps_.enable_early_data = true;
19823 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19824
19825 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19826
19827 TestCompletionCallback callback;
19828 auto trans =
19829 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19830
19831 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19832 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19833
19834 rv = callback.WaitForResult();
19835 EXPECT_THAT(rv, IsOk());
19836
19837 const HttpResponseInfo* response = trans->GetResponseInfo();
19838 ASSERT_TRUE(response);
19839 ASSERT_TRUE(response->headers);
19840 EXPECT_EQ(200, response->headers->response_code());
19841 EXPECT_EQ(1, response->headers->GetContentLength());
19842
19843 // Check that the Write didn't get called before ConfirmHandshake completed.
19844 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19845
19846 trans.reset();
19847
19848 session->CloseAllConnections();
19849}
19850
19851TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
19852 HttpRequestInfo request;
19853 request.method = "POST";
19854 request.url = GURL("https://www.example.org/");
19855 request.traffic_annotation =
19856 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19857
19858 MockWrite data_writes[] = {
19859 MockWrite(SYNCHRONOUS,
19860 "POST / HTTP/1.1\r\n"
19861 "Host: www.example.org\r\n"
19862 "Connection: keep-alive\r\n"
19863 "Content-Length: 0\r\n\r\n"),
19864 };
19865
Steven Valdez1c1859172019-04-10 15:33:2819866 MockRead data_reads[] = {
19867 MockRead("HTTP/1.1 200 OK\r\n"),
19868 MockRead("Content-Length: 1\r\n\r\n"),
19869 MockRead(SYNCHRONOUS, "1"),
19870 };
19871
19872 StaticSocketDataProvider data(data_reads, data_writes);
19873 session_deps_.socket_factory->AddSocketDataProvider(&data);
19874 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19875 ssl.confirm = MockConfirm(ASYNC, OK);
19876 session_deps_.enable_early_data = true;
19877 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19878
19879 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19880
19881 TestCompletionCallback callback;
19882 auto trans =
19883 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19884
19885 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19886 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19887
19888 rv = callback.WaitForResult();
19889 EXPECT_THAT(rv, IsOk());
19890
19891 const HttpResponseInfo* response = trans->GetResponseInfo();
19892 ASSERT_TRUE(response);
19893 ASSERT_TRUE(response->headers);
19894 EXPECT_EQ(200, response->headers->response_code());
19895 EXPECT_EQ(1, response->headers->GetContentLength());
19896
19897 // Check that the Write didn't get called before ConfirmHandshake completed.
19898 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19899
19900 trans.reset();
19901
19902 session->CloseAllConnections();
19903}
19904
19905TEST_F(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
19906 HttpRequestInfo request;
19907 request.method = "POST";
19908 request.url = GURL("https://www.example.org/");
19909 request.traffic_annotation =
19910 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19911
19912 MockWrite data_writes[] = {
19913 MockWrite(ASYNC,
19914 "POST / HTTP/1.1\r\n"
19915 "Host: www.example.org\r\n"
19916 "Connection: keep-alive\r\n"
19917 "Content-Length: 0\r\n\r\n"),
19918 };
19919
Steven Valdez1c1859172019-04-10 15:33:2819920 MockRead data_reads[] = {
19921 MockRead("HTTP/1.1 200 OK\r\n"),
19922 MockRead("Content-Length: 1\r\n\r\n"),
19923 MockRead(SYNCHRONOUS, "1"),
19924 };
19925
19926 StaticSocketDataProvider data(data_reads, data_writes);
19927 session_deps_.socket_factory->AddSocketDataProvider(&data);
19928 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
19929 ssl.confirm = MockConfirm(ASYNC, OK);
19930 session_deps_.enable_early_data = true;
19931 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19932
19933 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19934
19935 TestCompletionCallback callback;
19936 auto trans =
19937 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19938
19939 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
19940 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19941
19942 rv = callback.WaitForResult();
19943 EXPECT_THAT(rv, IsOk());
19944
19945 const HttpResponseInfo* response = trans->GetResponseInfo();
19946 ASSERT_TRUE(response);
19947 ASSERT_TRUE(response->headers);
19948 EXPECT_EQ(200, response->headers->response_code());
19949 EXPECT_EQ(1, response->headers->GetContentLength());
19950
19951 // Check that the Write didn't get called before ConfirmHandshake completed.
19952 ASSERT_FALSE(ssl.WriteBeforeConfirm());
19953
19954 trans.reset();
19955
19956 session->CloseAllConnections();
19957}
19958
David Benjaminfb976932019-05-15 13:39:1519959// 0-RTT rejects are handled at HttpNetworkTransaction.
19960TEST_F(HttpNetworkTransactionTest, ZeroRTTReject) {
19961 enum class RejectType {
19962 kRead,
19963 kWrite,
19964 kConfirm,
19965 };
19966
19967 for (RejectType type :
19968 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
19969 SCOPED_TRACE(static_cast<int>(type));
19970 for (Error reject_error :
19971 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
19972 SCOPED_TRACE(reject_error);
19973 session_deps_.socket_factory =
19974 std::make_unique<MockClientSocketFactory>();
19975
19976 HttpRequestInfo request;
19977 request.method = type == RejectType::kConfirm ? "POST" : "GET";
19978 request.url = GURL("https://www.example.org/");
19979 request.traffic_annotation =
19980 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19981
19982 // The first request fails.
19983 std::vector<MockWrite> data1_writes;
19984 std::vector<MockRead> data1_reads;
19985 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
19986 switch (type) {
19987 case RejectType::kRead:
19988 data1_writes.emplace_back(
19989 "GET / HTTP/1.1\r\n"
19990 "Host: www.example.org\r\n"
19991 "Connection: keep-alive\r\n\r\n");
19992 data1_reads.emplace_back(ASYNC, reject_error);
19993 // Cause ConfirmHandshake to hang (it should not be called).
19994 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
19995 break;
19996 case RejectType::kWrite:
19997 data1_writes.emplace_back(ASYNC, reject_error);
19998 // Cause ConfirmHandshake to hang (it should not be called).
19999 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
20000 break;
20001 case RejectType::kConfirm:
20002 // The request never gets far enough to read or write.
20003 ssl1.confirm = MockConfirm(ASYNC, reject_error);
20004 break;
20005 }
20006
20007 StaticSocketDataProvider data1(data1_reads, data1_writes);
20008 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20009 session_deps_.enable_early_data = true;
20010 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20011
20012 // The retry succeeds.
20013 //
20014 // TODO(https://crbug.com/950705): If |reject_error| is
20015 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
20016 MockWrite data2_writes[] = {
20017 request.method == "POST"
20018 ? MockWrite("POST / HTTP/1.1\r\n"
20019 "Host: www.example.org\r\n"
20020 "Connection: keep-alive\r\n"
20021 "Content-Length: 0\r\n\r\n")
20022 : MockWrite("GET / HTTP/1.1\r\n"
20023 "Host: www.example.org\r\n"
20024 "Connection: keep-alive\r\n\r\n"),
20025 };
20026
20027 MockRead data2_reads[] = {
20028 MockRead("HTTP/1.1 200 OK\r\n"),
20029 MockRead("Content-Length: 1\r\n\r\n"),
20030 MockRead(SYNCHRONOUS, "1"),
20031 };
20032
20033 StaticSocketDataProvider data2(data2_reads, data2_writes);
20034 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20035 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
20036 ssl2.confirm = MockConfirm(ASYNC, OK);
20037 session_deps_.enable_early_data = true;
20038 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20039
20040 std::unique_ptr<HttpNetworkSession> session(
20041 CreateSession(&session_deps_));
20042
20043 TestCompletionCallback callback;
20044 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20045 session.get());
20046
20047 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
20048 NetLogWithSource())),
20049 IsOk());
20050
20051 const HttpResponseInfo* response = trans->GetResponseInfo();
20052 ASSERT_TRUE(response);
20053 ASSERT_TRUE(response->headers);
20054 EXPECT_EQ(200, response->headers->response_code());
20055 EXPECT_EQ(1, response->headers->GetContentLength());
20056 }
20057 }
20058}
20059
Steven Valdez1c1859172019-04-10 15:33:2820060TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
20061 HttpRequestInfo request;
20062 request.method = "POST";
20063 request.url = GURL("https://www.example.org/");
20064 request.traffic_annotation =
20065 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20066
20067 MockWrite data_writes[] = {
20068 MockWrite("POST / HTTP/1.1\r\n"
20069 "Host: www.example.org\r\n"
20070 "Connection: keep-alive\r\n"
20071 "Content-Length: 0\r\n\r\n"),
20072 };
20073
Steven Valdez1c1859172019-04-10 15:33:2820074 MockRead data_reads[] = {
20075 MockRead("HTTP/1.1 200 OK\r\n"),
20076 MockRead("Content-Length: 1\r\n\r\n"),
20077 MockRead(SYNCHRONOUS, "1"),
20078 };
20079
20080 StaticSocketDataProvider data(data_reads, data_writes);
20081 session_deps_.socket_factory->AddSocketDataProvider(&data);
20082 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20083 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
20084 session_deps_.enable_early_data = true;
20085 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20086
20087 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20088
20089 TestCompletionCallback callback;
20090 auto trans =
20091 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20092
20093 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20094 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20095
20096 rv = callback.WaitForResult();
20097 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20098
20099 // Check that the Write didn't get called before ConfirmHandshake completed.
20100 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20101
20102 trans.reset();
20103
20104 session->CloseAllConnections();
20105}
20106
20107TEST_F(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
20108 HttpRequestInfo request;
20109 request.method = "POST";
20110 request.url = GURL("https://www.example.org/");
20111 request.traffic_annotation =
20112 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20113
20114 MockWrite data_writes[] = {
20115 MockWrite("POST / HTTP/1.1\r\n"
20116 "Host: www.example.org\r\n"
20117 "Connection: keep-alive\r\n"
20118 "Content-Length: 0\r\n\r\n"),
20119 };
20120
Steven Valdez1c1859172019-04-10 15:33:2820121 MockRead data_reads[] = {
20122 MockRead("HTTP/1.1 200 OK\r\n"),
20123 MockRead("Content-Length: 1\r\n\r\n"),
20124 MockRead(SYNCHRONOUS, "1"),
20125 };
20126
20127 StaticSocketDataProvider data(data_reads, data_writes);
20128 session_deps_.socket_factory->AddSocketDataProvider(&data);
20129 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
20130 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
20131 session_deps_.enable_early_data = true;
20132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
20133
20134 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20135
20136 TestCompletionCallback callback;
20137 auto trans =
20138 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20139
20140 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
20141 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20142
20143 rv = callback.WaitForResult();
20144 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
20145
20146 // Check that the Write didn't get called before ConfirmHandshake completed.
20147 ASSERT_FALSE(ssl.WriteBeforeConfirm());
20148
20149 trans.reset();
20150
20151 session->CloseAllConnections();
20152}
20153
David Benjamin2eb827f2019-04-29 18:31:0420154// Test the proxy and origin server each requesting both TLS client certificates
20155// and HTTP auth. This is a regression test for https://crbug.com/946406.
20156TEST_F(HttpNetworkTransactionTest, AuthEverything) {
20157 // Note these hosts must match the CheckBasic*Auth() functions.
20158 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20159 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20160
20161 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20162 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20163
20164 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20165 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20166 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20167 ASSERT_TRUE(identity_proxy);
20168
20169 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20170 cert_request_info_origin->host_and_port =
20171 HostPortPair("www.example.org", 443);
20172
20173 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20174 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20175 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20176 ASSERT_TRUE(identity_origin);
20177
20178 HttpRequestInfo request;
20179 request.method = "GET";
20180 request.url = GURL("https://www.example.org/");
20181 request.traffic_annotation =
20182 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20183
David Benjamin7ebab032019-04-30 21:51:3020184 // First, the client connects to the proxy, which requests a client
20185 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420186 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20187 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20188 ssl_proxy1.expected_send_client_cert = false;
David Benjamin2eb827f2019-04-29 18:31:0420189 StaticSocketDataProvider data1;
20190 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020191 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420192
David Benjamin7ebab032019-04-30 21:51:3020193 // The client responds with a certificate on a new connection. The handshake
20194 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420195 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20196 ssl_proxy2.expected_send_client_cert = true;
20197 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020198 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420199 std::vector<MockWrite> mock_writes2;
20200 std::vector<MockRead> mock_reads2;
20201 mock_writes2.emplace_back(
20202 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20203 "Host: www.example.org:443\r\n"
20204 "Proxy-Connection: keep-alive\r\n\r\n");
20205 mock_reads2.emplace_back(
20206 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20207 "Content-Length: 0\r\n"
20208 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020209 // The client retries with credentials.
David Benjamin2eb827f2019-04-29 18:31:0420210 mock_writes2.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"
David Benjamin7ebab032019-04-30 21:51:3020214 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420215 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20216 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20217 // The origin requests client certificates.
20218 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20219 ssl_origin2.cert_request_info = cert_request_info_origin.get();
David Benjamin2eb827f2019-04-29 18:31:0420220 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20221 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020222 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20223 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
David Benjamin2eb827f2019-04-29 18:31:0420224
David Benjamin7ebab032019-04-30 21:51:3020225 // The client responds to the origin client certificate request on a new
20226 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420227 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20228 ssl_proxy3.expected_send_client_cert = true;
20229 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
David Benjamin2eb827f2019-04-29 18:31:0420230 std::vector<MockWrite> mock_writes3;
20231 std::vector<MockRead> mock_reads3;
20232 mock_writes3.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"
David Benjamin7ebab032019-04-30 21:51:3020236 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420237 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20238 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20239 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
20240 ssl_origin3.expected_send_client_cert = true;
20241 ssl_origin3.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020242 // The client sends the origin HTTP request, which results in another HTTP
20243 // auth request.
David Benjamin2eb827f2019-04-29 18:31:0420244 mock_writes3.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_reads3.emplace_back(
20249 "HTTP/1.1 401 Unauthorized\r\n"
20250 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20251 "Content-Length: 0\r\n\r\n");
David Benjamin7ebab032019-04-30 21:51:3020252 // The client retries with credentials, and the request finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420253 mock_writes3.emplace_back(
20254 "GET / HTTP/1.1\r\n"
20255 "Host: www.example.org\r\n"
20256 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020257 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420258 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20259 mock_reads3.emplace_back(
20260 "HTTP/1.1 200 OK\r\n"
20261 "Content-Length: 0\r\n\r\n");
20262 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20263 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020264 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420266
20267 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20268
20269 // Start the request.
20270 TestCompletionCallback callback;
20271 auto trans =
20272 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20273 int rv = callback.GetResult(
20274 trans->Start(&request, callback.callback(), NetLogWithSource()));
20275
20276 // Handle the proxy client certificate challenge.
20277 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20278 SSLCertRequestInfo* cert_request_info =
20279 trans->GetResponseInfo()->cert_request_info.get();
20280 ASSERT_TRUE(cert_request_info);
20281 EXPECT_TRUE(cert_request_info->is_proxy);
20282 EXPECT_EQ(cert_request_info->host_and_port,
20283 cert_request_info_proxy->host_and_port);
20284 rv = callback.GetResult(trans->RestartWithCertificate(
20285 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20286 callback.callback()));
20287
20288 // Handle the proxy HTTP auth challenge.
20289 ASSERT_THAT(rv, IsOk());
20290 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20291 EXPECT_TRUE(
20292 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20293 rv = callback.GetResult(trans->RestartWithAuth(
20294 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20295 callback.callback()));
20296
20297 // Handle the origin client certificate challenge.
20298 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20299 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20300 ASSERT_TRUE(cert_request_info);
20301 EXPECT_FALSE(cert_request_info->is_proxy);
20302 EXPECT_EQ(cert_request_info->host_and_port,
20303 cert_request_info_origin->host_and_port);
20304 rv = callback.GetResult(trans->RestartWithCertificate(
20305 identity_origin->certificate(), identity_origin->ssl_private_key(),
20306 callback.callback()));
20307
20308 // Handle the origin HTTP auth challenge.
20309 ASSERT_THAT(rv, IsOk());
20310 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20311 EXPECT_TRUE(
20312 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20313 rv = callback.GetResult(trans->RestartWithAuth(
20314 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20315 callback.callback()));
20316
20317 // The request completes.
20318 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020319 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420320}
20321
20322// Test the proxy and origin server each requesting both TLS client certificates
20323// and HTTP auth and each HTTP auth closing the connection. This is a regression
20324// test for https://crbug.com/946406.
20325TEST_F(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
20326 // Note these hosts must match the CheckBasic*Auth() functions.
20327 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20328 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20329
20330 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
20331 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
20332
20333 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
20334 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20335 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20336 ASSERT_TRUE(identity_proxy);
20337
20338 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20339 cert_request_info_origin->host_and_port =
20340 HostPortPair("www.example.org", 443);
20341
20342 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20343 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20344 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20345 ASSERT_TRUE(identity_origin);
20346
20347 HttpRequestInfo request;
20348 request.method = "GET";
20349 request.url = GURL("https://www.example.org/");
20350 request.traffic_annotation =
20351 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20352
David Benjamin7ebab032019-04-30 21:51:3020353 // First, the client connects to the proxy, which requests a client
20354 // certificate.
David Benjamin2eb827f2019-04-29 18:31:0420355 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20356 ssl_proxy1.cert_request_info = cert_request_info_proxy.get();
20357 ssl_proxy1.expected_send_client_cert = false;
20358 StaticSocketDataProvider data1;
20359 session_deps_.socket_factory->AddSocketDataProvider(&data1);
David Benjamin7ebab032019-04-30 21:51:3020360 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
David Benjamin2eb827f2019-04-29 18:31:0420361
David Benjamin7ebab032019-04-30 21:51:3020362 // The client responds with a certificate on a new connection. The handshake
20363 // succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420364 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20365 ssl_proxy2.expected_send_client_cert = true;
20366 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
David Benjamin7ebab032019-04-30 21:51:3020367 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
David Benjamin2eb827f2019-04-29 18:31:0420368 std::vector<MockWrite> mock_writes2;
20369 std::vector<MockRead> mock_reads2;
20370 mock_writes2.emplace_back(
20371 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20372 "Host: www.example.org:443\r\n"
20373 "Proxy-Connection: keep-alive\r\n\r\n");
20374 mock_reads2.emplace_back(
20375 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20376 "Content-Length: 0\r\n"
20377 "Proxy-Connection: close\r\n"
20378 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20379 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20380 session_deps_.socket_factory->AddSocketDataProvider(&data2);
David Benjamin7ebab032019-04-30 21:51:3020381 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
David Benjamin2eb827f2019-04-29 18:31:0420382
David Benjamin7ebab032019-04-30 21:51:3020383 // The client retries with credentials on a new connection.
David Benjamin2eb827f2019-04-29 18:31:0420384 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
20385 ssl_proxy3.expected_send_client_cert = true;
20386 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
20387 std::vector<MockWrite> mock_writes3;
20388 std::vector<MockRead> mock_reads3;
20389 mock_writes3.emplace_back(
20390 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20391 "Host: www.example.org:443\r\n"
20392 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020393 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420394 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20395 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20396 // The origin requests client certificates.
20397 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20398 ssl_origin3.cert_request_info = cert_request_info_origin.get();
20399 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
20400 session_deps_.socket_factory->AddSocketDataProvider(&data3);
David Benjamin7ebab032019-04-30 21:51:3020401 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
20402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
David Benjamin2eb827f2019-04-29 18:31:0420403
David Benjamin7ebab032019-04-30 21:51:3020404 // The client responds to the origin client certificate request on a new
20405 // connection.
David Benjamin2eb827f2019-04-29 18:31:0420406 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
20407 ssl_proxy4.expected_send_client_cert = true;
20408 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
20409 std::vector<MockWrite> mock_writes4;
20410 std::vector<MockRead> mock_reads4;
20411 mock_writes4.emplace_back(
20412 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20413 "Host: www.example.org:443\r\n"
20414 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020415 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420416 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20417 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20418 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
20419 ssl_origin4.expected_send_client_cert = true;
20420 ssl_origin4.expected_client_cert = identity_origin->certificate();
David Benjamin7ebab032019-04-30 21:51:3020421 // The client sends the origin HTTP request, which results in another HTTP
20422 // auth request and closed connection.
David Benjamin2eb827f2019-04-29 18:31:0420423 mock_writes4.emplace_back(
20424 "GET / HTTP/1.1\r\n"
20425 "Host: www.example.org\r\n"
20426 "Connection: keep-alive\r\n\r\n");
20427 mock_reads4.emplace_back(
20428 "HTTP/1.1 401 Unauthorized\r\n"
20429 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
20430 "Connection: close\r\n"
20431 "Content-Length: 0\r\n\r\n");
20432 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
20433 session_deps_.socket_factory->AddSocketDataProvider(&data4);
David Benjamin7ebab032019-04-30 21:51:3020434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
20435 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
David Benjamin2eb827f2019-04-29 18:31:0420436
David Benjamin7ebab032019-04-30 21:51:3020437 // The client retries with credentials on a new connection, and the request
20438 // finally succeeds.
David Benjamin2eb827f2019-04-29 18:31:0420439 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
20440 ssl_proxy5.expected_send_client_cert = true;
20441 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
20442 std::vector<MockWrite> mock_writes5;
20443 std::vector<MockRead> mock_reads5;
20444 mock_writes5.emplace_back(
20445 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20446 "Host: www.example.org:443\r\n"
20447 "Proxy-Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020448 // Authenticate as proxyuser:proxypass.
David Benjamin2eb827f2019-04-29 18:31:0420449 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20450 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20451 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
20452 ssl_origin5.expected_send_client_cert = true;
20453 ssl_origin5.expected_client_cert = identity_origin->certificate();
20454 mock_writes5.emplace_back(
20455 "GET / HTTP/1.1\r\n"
20456 "Host: www.example.org\r\n"
20457 "Connection: keep-alive\r\n"
David Benjamin7ebab032019-04-30 21:51:3020458 // Authenticate as user:pass.
David Benjamin2eb827f2019-04-29 18:31:0420459 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
20460 mock_reads5.emplace_back(
20461 "HTTP/1.1 200 OK\r\n"
20462 "Connection: close\r\n"
20463 "Content-Length: 0\r\n\r\n");
20464 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
20465 session_deps_.socket_factory->AddSocketDataProvider(&data5);
David Benjamin7ebab032019-04-30 21:51:3020466 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
20467 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
David Benjamin2eb827f2019-04-29 18:31:0420468
20469 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20470
20471 // Start the request.
20472 TestCompletionCallback callback;
20473 auto trans =
20474 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20475 int rv = callback.GetResult(
20476 trans->Start(&request, callback.callback(), NetLogWithSource()));
20477
20478 // Handle the proxy client certificate challenge.
20479 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20480 SSLCertRequestInfo* cert_request_info =
20481 trans->GetResponseInfo()->cert_request_info.get();
20482 ASSERT_TRUE(cert_request_info);
20483 EXPECT_TRUE(cert_request_info->is_proxy);
20484 EXPECT_EQ(cert_request_info->host_and_port,
20485 cert_request_info_proxy->host_and_port);
20486 rv = callback.GetResult(trans->RestartWithCertificate(
20487 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
20488 callback.callback()));
20489
20490 // Handle the proxy HTTP auth challenge.
20491 ASSERT_THAT(rv, IsOk());
20492 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20493 EXPECT_TRUE(
20494 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20495 rv = callback.GetResult(trans->RestartWithAuth(
20496 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20497 callback.callback()));
20498
20499 // Handle the origin client certificate challenge.
20500 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20501 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
20502 ASSERT_TRUE(cert_request_info);
20503 EXPECT_FALSE(cert_request_info->is_proxy);
20504 EXPECT_EQ(cert_request_info->host_and_port,
20505 cert_request_info_origin->host_and_port);
20506 rv = callback.GetResult(trans->RestartWithCertificate(
20507 identity_origin->certificate(), identity_origin->ssl_private_key(),
20508 callback.callback()));
20509
20510 // Handle the origin HTTP auth challenge.
20511 ASSERT_THAT(rv, IsOk());
20512 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
20513 EXPECT_TRUE(
20514 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
20515 rv = callback.GetResult(trans->RestartWithAuth(
20516 AuthCredentials(ASCIIToUTF16("user"), ASCIIToUTF16("pass")),
20517 callback.callback()));
20518
20519 // The request completes.
20520 ASSERT_THAT(rv, IsOk());
David Benjamin7ebab032019-04-30 21:51:3020521 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20522}
20523
20524// Test the proxy requesting HTTP auth and the server requesting TLS client
20525// certificates. This is a regression test for https://crbug.com/946406.
20526TEST_F(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
20527 // Note these hosts must match the CheckBasic*Auth() functions.
20528 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
20529 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20530
20531 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
20532 cert_request_info_origin->host_and_port =
20533 HostPortPair("www.example.org", 443);
20534
20535 std::unique_ptr<FakeClientCertIdentity> identity_origin =
20536 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20537 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
20538 ASSERT_TRUE(identity_origin);
20539
20540 HttpRequestInfo request;
20541 request.method = "GET";
20542 request.url = GURL("https://www.example.org/");
20543 request.traffic_annotation =
20544 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20545
20546 // The client connects to the proxy. The handshake succeeds.
20547 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
20548 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
20549 std::vector<MockWrite> mock_writes1;
20550 std::vector<MockRead> mock_reads1;
20551 mock_writes1.emplace_back(
20552 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20553 "Host: www.example.org:443\r\n"
20554 "Proxy-Connection: keep-alive\r\n\r\n");
20555 mock_reads1.emplace_back(
20556 "HTTP/1.1 407 Proxy Authentication Required\r\n"
20557 "Content-Length: 0\r\n"
20558 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
20559 // The client retries with credentials, and the request finally succeeds.
20560 mock_writes1.emplace_back(
20561 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20562 "Host: www.example.org:443\r\n"
20563 "Proxy-Connection: keep-alive\r\n"
20564 // Authenticate as proxyuser:proxypass.
20565 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20566 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20567 // The origin requests client certificates.
20568 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20569 ssl_origin1.cert_request_info = cert_request_info_origin.get();
20570 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
20571 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20572 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
20573 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
20574
20575 // The client responds to the origin client certificate request on a new
20576 // connection.
20577 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
20578 std::vector<MockWrite> mock_writes2;
20579 std::vector<MockRead> mock_reads2;
20580 mock_writes2.emplace_back(
20581 "CONNECT www.example.org:443 HTTP/1.1\r\n"
20582 "Host: www.example.org:443\r\n"
20583 "Proxy-Connection: keep-alive\r\n"
20584 // Authenticate as proxyuser:proxypass.
20585 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
20586 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
20587 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
20588 ssl_origin2.expected_send_client_cert = true;
20589 ssl_origin2.expected_client_cert = identity_origin->certificate();
20590 // The client sends the origin HTTP request, which succeeds.
20591 mock_writes2.emplace_back(
20592 "GET / HTTP/1.1\r\n"
20593 "Host: www.example.org\r\n"
20594 "Connection: keep-alive\r\n\r\n");
20595 mock_reads2.emplace_back(
20596 "HTTP/1.1 200 OK\r\n"
20597 "Content-Length: 0\r\n\r\n");
20598 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
20599 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20600 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
20601 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
20602
20603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20604
20605 // Start the request.
20606 TestCompletionCallback callback;
20607 auto trans =
20608 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20609 int rv = callback.GetResult(
20610 trans->Start(&request, callback.callback(), NetLogWithSource()));
20611
20612 // Handle the proxy HTTP auth challenge.
20613 ASSERT_THAT(rv, IsOk());
20614 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
20615 EXPECT_TRUE(
20616 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
20617 rv = callback.GetResult(trans->RestartWithAuth(
20618 AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")),
20619 callback.callback()));
20620
20621 // Handle the origin client certificate challenge.
20622 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20623 SSLCertRequestInfo* cert_request_info =
20624 trans->GetResponseInfo()->cert_request_info.get();
20625 ASSERT_TRUE(cert_request_info);
20626 EXPECT_FALSE(cert_request_info->is_proxy);
20627 EXPECT_EQ(cert_request_info->host_and_port,
20628 cert_request_info_origin->host_and_port);
20629 rv = callback.GetResult(trans->RestartWithCertificate(
20630 identity_origin->certificate(), identity_origin->ssl_private_key(),
20631 callback.callback()));
20632
20633 // The request completes.
20634 ASSERT_THAT(rv, IsOk());
20635 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
David Benjamin2eb827f2019-04-29 18:31:0420636}
20637
David Benjamin6e673a82019-04-30 22:52:5820638// Test that socket reuse works with client certificates.
20639TEST_F(HttpNetworkTransactionTest, ClientCertSocketReuse) {
20640 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
20641 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
20642
20643 std::unique_ptr<FakeClientCertIdentity> identity =
20644 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
20645 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
20646 ASSERT_TRUE(identity);
20647
20648 HttpRequestInfo request1;
20649 request1.method = "GET";
20650 request1.url = GURL("https://www.example.org/a");
20651 request1.traffic_annotation =
20652 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20653
20654 HttpRequestInfo request2;
20655 request2.method = "GET";
20656 request2.url = GURL("https://www.example.org/b");
20657 request2.traffic_annotation =
20658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20659
20660 // The first connection results in a client certificate request.
20661 StaticSocketDataProvider data1;
20662 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20663 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
20664 ssl1.cert_request_info = cert_request_info.get();
20665 ssl1.expected_send_client_cert = false;
20666 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
20667
20668 // The second connection succeeds and is usable for both requests.
20669 MockWrite mock_writes[] = {
20670 MockWrite("GET /a HTTP/1.1\r\n"
20671 "Host: www.example.org\r\n"
20672 "Connection: keep-alive\r\n\r\n"),
20673 MockWrite("GET /b HTTP/1.1\r\n"
20674 "Host: www.example.org\r\n"
20675 "Connection: keep-alive\r\n\r\n"),
20676 };
20677 MockRead mock_reads[] = {
20678 MockRead("HTTP/1.1 200 OK\r\n"
20679 "Content-Length: 0\r\n\r\n"),
20680 MockRead("HTTP/1.1 200 OK\r\n"
20681 "Content-Length: 0\r\n\r\n"),
20682 };
20683 StaticSocketDataProvider data2(mock_reads, mock_writes);
20684 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20685 SSLSocketDataProvider ssl2(ASYNC, OK);
20686 ssl2.expected_send_client_cert = true;
20687 ssl2.expected_client_cert = identity->certificate();
20688 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
20689
20690 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20691
20692 // Start the first request. It succeeds after providing client certificates.
20693 TestCompletionCallback callback;
20694 auto trans =
20695 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20696 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
20697 NetLogWithSource())),
20698 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
20699
20700 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
20701 ASSERT_TRUE(info);
20702 EXPECT_FALSE(info->is_proxy);
20703 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
20704
20705 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
20706 identity->certificate(), identity->ssl_private_key(),
20707 callback.callback())),
20708 IsOk());
20709 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20710
20711 // Make the second request. It completes without requesting client
20712 // certificates.
20713 trans =
20714 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
20715 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
20716 NetLogWithSource())),
20717 IsOk());
20718 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
20719}
20720
Matt Menke166443c2019-05-24 18:45:5920721// Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
20722// sequence with two different NetworkIsolationKeys, the first and last have the
20723// same key, the second a different one. Checks that the requests are
20724// partitioned across sockets as expected.
20725TEST_F(HttpNetworkTransactionTest, NetworkIsolation) {
20726 NetworkIsolationKey network_isolation_key1(
20727 url::Origin::Create(GURL("http://origin1/")));
20728 NetworkIsolationKey network_isolation_key2(
20729 url::Origin::Create(GURL("http://origin2/")));
20730
20731 for (bool partition_connections : {false, true}) {
20732 SCOPED_TRACE(partition_connections);
20733
20734 base::test::ScopedFeatureList feature_list;
20735 if (partition_connections) {
20736 feature_list.InitAndEnableFeature(
20737 features::kPartitionConnectionsByNetworkIsolationKey);
20738 } else {
20739 feature_list.InitAndDisableFeature(
20740 features::kPartitionConnectionsByNetworkIsolationKey);
20741 }
20742
20743 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20744
20745 // Reads and writes for the unpartitioned case, where only one socket is
20746 // used.
20747
20748 const MockWrite kUnpartitionedWrites[] = {
20749 MockWrite("GET /1 HTTP/1.1\r\n"
20750 "Host: foo.test\r\n"
20751 "Connection: keep-alive\r\n\r\n"),
20752 MockWrite("GET /2 HTTP/1.1\r\n"
20753 "Host: foo.test\r\n"
20754 "Connection: keep-alive\r\n\r\n"),
20755 MockWrite("GET /3 HTTP/1.1\r\n"
20756 "Host: foo.test\r\n"
20757 "Connection: keep-alive\r\n\r\n"),
20758 };
20759
20760 const MockRead kUnpartitionedReads[] = {
20761 MockRead("HTTP/1.1 200 OK\r\n"
20762 "Connection: keep-alive\r\n"
20763 "Content-Length: 1\r\n\r\n"
20764 "1"),
20765 MockRead("HTTP/1.1 200 OK\r\n"
20766 "Connection: keep-alive\r\n"
20767 "Content-Length: 1\r\n\r\n"
20768 "2"),
20769 MockRead("HTTP/1.1 200 OK\r\n"
20770 "Connection: keep-alive\r\n"
20771 "Content-Length: 1\r\n\r\n"
20772 "3"),
20773 };
20774
20775 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
20776 kUnpartitionedWrites);
20777
20778 // Reads and writes for the partitioned case, where two sockets are used.
20779
20780 const MockWrite kPartitionedWrites1[] = {
20781 MockWrite("GET /1 HTTP/1.1\r\n"
20782 "Host: foo.test\r\n"
20783 "Connection: keep-alive\r\n\r\n"),
20784 MockWrite("GET /3 HTTP/1.1\r\n"
20785 "Host: foo.test\r\n"
20786 "Connection: keep-alive\r\n\r\n"),
20787 };
20788
20789 const MockRead kPartitionedReads1[] = {
20790 MockRead("HTTP/1.1 200 OK\r\n"
20791 "Connection: keep-alive\r\n"
20792 "Content-Length: 1\r\n\r\n"
20793 "1"),
20794 MockRead("HTTP/1.1 200 OK\r\n"
20795 "Connection: keep-alive\r\n"
20796 "Content-Length: 1\r\n\r\n"
20797 "3"),
20798 };
20799
20800 const MockWrite kPartitionedWrites2[] = {
20801 MockWrite("GET /2 HTTP/1.1\r\n"
20802 "Host: foo.test\r\n"
20803 "Connection: keep-alive\r\n\r\n"),
20804 };
20805
20806 const MockRead kPartitionedReads2[] = {
20807 MockRead("HTTP/1.1 200 OK\r\n"
20808 "Connection: keep-alive\r\n"
20809 "Content-Length: 1\r\n\r\n"
20810 "2"),
20811 };
20812
20813 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
20814 kPartitionedWrites1);
20815 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
20816 kPartitionedWrites2);
20817
20818 if (partition_connections) {
20819 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
20820 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
20821 } else {
20822 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
20823 }
20824
20825 TestCompletionCallback callback;
20826 HttpRequestInfo request1;
20827 request1.method = "GET";
20828 request1.url = GURL("http://foo.test/1");
20829 request1.traffic_annotation =
20830 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20831 request1.network_isolation_key = network_isolation_key1;
20832 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20833 session.get());
20834 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
20835 EXPECT_THAT(callback.GetResult(rv), IsOk());
20836 std::string response_data1;
20837 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
20838 EXPECT_EQ("1", response_data1);
20839 trans1.reset();
20840
20841 HttpRequestInfo request2;
20842 request2.method = "GET";
20843 request2.url = GURL("http://foo.test/2");
20844 request2.traffic_annotation =
20845 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20846 request2.network_isolation_key = network_isolation_key2;
20847 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20848 session.get());
20849 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
20850 EXPECT_THAT(callback.GetResult(rv), IsOk());
20851 std::string response_data2;
20852 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
20853 EXPECT_EQ("2", response_data2);
20854 trans2.reset();
20855
20856 HttpRequestInfo request3;
20857 request3.method = "GET";
20858 request3.url = GURL("http://foo.test/3");
20859 request3.traffic_annotation =
20860 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20861 request3.network_isolation_key = network_isolation_key1;
20862 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
20863 session.get());
20864 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
20865 EXPECT_THAT(callback.GetResult(rv), IsOk());
20866 std::string response_data3;
20867 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
20868 EXPECT_EQ("3", response_data3);
20869 trans3.reset();
20870 }
20871}
20872
Matt Menkeae58eeb2019-05-24 21:09:5020873TEST_F(HttpNetworkTransactionTest, NetworkIsolationH2) {
20874 NetworkIsolationKey network_isolation_key1(
20875 url::Origin::Create(GURL("http://origin1/")));
20876 NetworkIsolationKey network_isolation_key2(
20877 url::Origin::Create(GURL("http://origin2/")));
20878
20879 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
20880 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
20881 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
20882 // the same way as the HTTP over H2 proxy case.
20883 for (bool use_proxy : {false, true}) {
20884 SCOPED_TRACE(use_proxy);
20885 if (use_proxy) {
20886 session_deps_.proxy_resolution_service =
20887 ProxyResolutionService::CreateFixedFromPacResult(
20888 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
20889 } else {
20890 session_deps_.proxy_resolution_service =
20891 ProxyResolutionService::CreateDirect();
20892 }
20893 const char* url1 = nullptr;
20894 const char* url2 = nullptr;
20895 const char* url3 = nullptr;
20896 if (use_proxy) {
20897 url1 = "http://foo.test/1";
20898 url2 = "http://foo.test/2";
20899 url3 = "http://foo.test/3";
20900 } else {
20901 url1 = "https://foo.test/1";
20902 url2 = "https://foo.test/2";
20903 url3 = "https://foo.test/3";
20904 }
20905
20906 for (bool partition_connections : {false, true}) {
20907 SCOPED_TRACE(partition_connections);
20908
20909 base::test::ScopedFeatureList feature_list;
20910 if (partition_connections) {
20911 feature_list.InitAndEnableFeature(
20912 features::kPartitionConnectionsByNetworkIsolationKey);
20913 } else {
20914 feature_list.InitAndDisableFeature(
20915 features::kPartitionConnectionsByNetworkIsolationKey);
20916 }
20917
20918 std::unique_ptr<HttpNetworkSession> session(
20919 CreateSession(&session_deps_));
20920
20921 // Reads and writes for the unpartitioned case, where only one socket is
20922 // used.
20923
20924 SpdyTestUtil spdy_util;
20925 spdy::SpdySerializedFrame unpartitioned_req1(
20926 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
20927 spdy::SpdySerializedFrame unpartitioned_response1(
20928 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20929 spdy::SpdySerializedFrame unpartitioned_body1(
20930 spdy_util.ConstructSpdyDataFrame(1, "1", true));
20931 spdy_util.UpdateWithStreamDestruction(1);
20932
20933 spdy::SpdySerializedFrame unpartitioned_req2(
20934 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
20935 spdy::SpdySerializedFrame unpartitioned_response2(
20936 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
20937 spdy::SpdySerializedFrame unpartitioned_body2(
20938 spdy_util.ConstructSpdyDataFrame(3, "2", true));
20939 spdy_util.UpdateWithStreamDestruction(3);
20940
20941 spdy::SpdySerializedFrame unpartitioned_req3(
20942 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
20943 spdy::SpdySerializedFrame unpartitioned_response3(
20944 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
20945 spdy::SpdySerializedFrame unpartitioned_body3(
20946 spdy_util.ConstructSpdyDataFrame(5, "3", true));
20947
20948 const MockWrite kUnpartitionedWrites[] = {
20949 CreateMockWrite(unpartitioned_req1, 0),
20950 CreateMockWrite(unpartitioned_req2, 3),
20951 CreateMockWrite(unpartitioned_req3, 6),
20952 };
20953
20954 const MockRead kUnpartitionedReads[] = {
20955 CreateMockRead(unpartitioned_response1, 1),
20956 CreateMockRead(unpartitioned_body1, 2),
20957 CreateMockRead(unpartitioned_response2, 4),
20958 CreateMockRead(unpartitioned_body2, 5),
20959 CreateMockRead(unpartitioned_response3, 7),
20960 CreateMockRead(unpartitioned_body3, 8),
20961 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
20962 };
20963
20964 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
20965 kUnpartitionedWrites);
20966
20967 // Reads and writes for the partitioned case, where two sockets are used.
20968
20969 SpdyTestUtil spdy_util2;
20970 spdy::SpdySerializedFrame partitioned_req1(
20971 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
20972 spdy::SpdySerializedFrame partitioned_response1(
20973 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20974 spdy::SpdySerializedFrame partitioned_body1(
20975 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
20976 spdy_util2.UpdateWithStreamDestruction(1);
20977
20978 spdy::SpdySerializedFrame partitioned_req3(
20979 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
20980 spdy::SpdySerializedFrame partitioned_response3(
20981 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
20982 spdy::SpdySerializedFrame partitioned_body3(
20983 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
20984
20985 const MockWrite kPartitionedWrites1[] = {
20986 CreateMockWrite(partitioned_req1, 0),
20987 CreateMockWrite(partitioned_req3, 3),
20988 };
20989
20990 const MockRead kPartitionedReads1[] = {
20991 CreateMockRead(partitioned_response1, 1),
20992 CreateMockRead(partitioned_body1, 2),
20993 CreateMockRead(partitioned_response3, 4),
20994 CreateMockRead(partitioned_body3, 5),
20995 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
20996 };
20997
20998 SpdyTestUtil spdy_util3;
20999 spdy::SpdySerializedFrame partitioned_req2(
21000 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
21001 spdy::SpdySerializedFrame partitioned_response2(
21002 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
21003 spdy::SpdySerializedFrame partitioned_body2(
21004 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
21005
21006 const MockWrite kPartitionedWrites2[] = {
21007 CreateMockWrite(partitioned_req2, 0),
21008 };
21009
21010 const MockRead kPartitionedReads2[] = {
21011 CreateMockRead(partitioned_response2, 1),
21012 CreateMockRead(partitioned_body2, 2),
21013 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21014 };
21015
21016 SequencedSocketData partitioned_data1(kPartitionedReads1,
21017 kPartitionedWrites1);
21018 SequencedSocketData partitioned_data2(kPartitionedReads2,
21019 kPartitionedWrites2);
21020
21021 // No need to segment SSLDataProviders by whether or not partitioning is
21022 // enabled.
21023 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21024 ssl_data1.next_proto = kProtoHTTP2;
21025 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21026 ssl_data2.next_proto = kProtoHTTP2;
21027
21028 if (partition_connections) {
21029 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
21030 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21031 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
21032 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21033 } else {
21034 session_deps_.socket_factory->AddSocketDataProvider(
21035 &unpartitioned_data);
21036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21037 }
21038
21039 TestCompletionCallback callback;
21040 HttpRequestInfo request1;
21041 request1.method = "GET";
21042 request1.url = GURL(url1);
21043 request1.traffic_annotation =
21044 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21045 request1.network_isolation_key = network_isolation_key1;
21046 auto trans1 =
21047 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21048 int rv =
21049 trans1->Start(&request1, callback.callback(), NetLogWithSource());
21050 EXPECT_THAT(callback.GetResult(rv), IsOk());
21051 std::string response_data1;
21052 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21053 EXPECT_EQ("1", response_data1);
21054 trans1.reset();
21055
21056 HttpRequestInfo request2;
21057 request2.method = "GET";
21058 request2.url = GURL(url2);
21059 request2.traffic_annotation =
21060 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21061 request2.network_isolation_key = network_isolation_key2;
21062 auto trans2 =
21063 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21064 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21065 EXPECT_THAT(callback.GetResult(rv), IsOk());
21066 std::string response_data2;
21067 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21068 EXPECT_EQ("2", response_data2);
21069 trans2.reset();
21070
21071 HttpRequestInfo request3;
21072 request3.method = "GET";
21073 request3.url = GURL(url3);
21074 request3.traffic_annotation =
21075 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21076 request3.network_isolation_key = network_isolation_key1;
21077 auto trans3 =
21078 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
21079 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21080 EXPECT_THAT(callback.GetResult(rv), IsOk());
21081 std::string response_data3;
21082 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21083 EXPECT_EQ("3", response_data3);
21084 trans3.reset();
21085 }
21086 }
21087}
21088
Matt Menke7281f872019-06-25 19:29:2521089// Preconnect two sockets with different NetworkIsolationKeys when
21090// features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then issue a
21091// request and make sure the correct socket is used. Loops three times,
21092// expecting to use the first preconnect, second preconnect, and neither.
21093TEST_F(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
21094 base::test::ScopedFeatureList feature_list;
21095 feature_list.InitAndEnableFeature(
21096 features::kPartitionConnectionsByNetworkIsolationKey);
21097
21098 enum class TestCase {
21099 kUseFirstPreconnect,
21100 kUseSecondPreconnect,
21101 kDontUsePreconnect,
21102 };
21103
21104 NetworkIsolationKey preconnect1_isolation_key(
21105 url::Origin::Create(GURL("http://origin1/")));
21106 NetworkIsolationKey preconnect2_isolation_key(
21107 url::Origin::Create(GURL("http://origin2/")));
21108 NetworkIsolationKey not_preconnected_isolation_key(
21109 url::Origin::Create(GURL("http://origin3/")));
21110
21111 // Test that only preconnects with
21112 for (TestCase test_case :
21113 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
21114 TestCase::kDontUsePreconnect}) {
21115 SpdySessionDependencies session_deps;
21116 // Make DNS lookups completely synchronously, so preconnects complete
21117 // immediately.
21118 session_deps.host_resolver->set_synchronous_mode(true);
21119
21120 const MockWrite kMockWrites[] = {
21121 MockWrite(ASYNC, 0,
21122 "GET / HTTP/1.1\r\n"
21123 "Host: www.foo.com\r\n"
21124 "Connection: keep-alive\r\n\r\n"),
21125 };
21126
21127 const MockRead kMockReads[] = {
21128 MockRead(ASYNC, 1,
21129 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
21130 "hello"),
21131 };
21132
21133 // Used for the socket that will actually be used, which may or may not be
21134 // one of the preconnects
21135 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
21136 kMockReads, kMockWrites);
21137
21138 // Used for the preconnects that won't actually be used.
21139 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
21140 base::span<const MockRead>(),
21141 base::span<const MockWrite>());
21142 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
21143 base::span<const MockRead>(),
21144 base::span<const MockWrite>());
21145
21146 NetworkIsolationKey network_isolation_key_for_request;
21147
21148 switch (test_case) {
21149 case TestCase::kUseFirstPreconnect:
21150 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21151 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21152 network_isolation_key_for_request = preconnect1_isolation_key;
21153 break;
21154 case TestCase::kUseSecondPreconnect:
21155 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21156 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21157 network_isolation_key_for_request = preconnect2_isolation_key;
21158 break;
21159 case TestCase::kDontUsePreconnect:
21160 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
21161 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
21162 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
21163 network_isolation_key_for_request = not_preconnected_isolation_key;
21164 break;
21165 }
21166
21167 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
21168
21169 // Preconnect sockets.
21170 HttpRequestInfo request;
21171 request.method = "GET";
21172 request.url = GURL("http://www.foo.com/");
21173 request.traffic_annotation =
21174 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21175
21176 request.network_isolation_key = preconnect1_isolation_key;
21177 session->http_stream_factory()->PreconnectStreams(1, request);
21178
21179 request.network_isolation_key = preconnect2_isolation_key;
21180 session->http_stream_factory()->PreconnectStreams(1, request);
21181
21182 request.network_isolation_key = network_isolation_key_for_request;
21183
21184 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21185
21186 // Make the request.
21187 TestCompletionCallback callback;
21188
21189 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21190
21191 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
21192 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21193
21194 rv = callback.WaitForResult();
21195 EXPECT_THAT(rv, IsOk());
21196
21197 const HttpResponseInfo* response = trans.GetResponseInfo();
21198 ASSERT_TRUE(response);
21199 ASSERT_TRUE(response->headers);
21200 EXPECT_EQ(200, response->headers->response_code());
21201
21202 std::string response_data;
21203 rv = ReadTransaction(&trans, &response_data);
21204 EXPECT_THAT(rv, IsOk());
21205 EXPECT_EQ("hello", response_data);
21206
21207 if (test_case != TestCase::kDontUsePreconnect) {
21208 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
21209 } else {
21210 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
21211 }
21212 }
21213}
21214
David Benjamin6f2da652019-06-26 23:36:3521215// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21216// cache is isolated.
21217TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSL) {
21218 base::test::ScopedFeatureList feature_list;
21219 feature_list.InitWithFeatures(
21220 {features::kPartitionConnectionsByNetworkIsolationKey,
21221 features::kPartitionSSLSessionsByNetworkIsolationKey},
21222 {});
21223
21224 const NetworkIsolationKey kNetworkIsolationKey1(
21225 url::Origin::Create(GURL("http://origin1/")));
21226 const NetworkIsolationKey kNetworkIsolationKey2(
21227 url::Origin::Create(GURL("http://origin2/")));
21228 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21229
21230 // The server always sends Connection: close, so each request goes over a
21231 // distinct socket.
21232
21233 const MockWrite kWrites1[] = {
21234 MockWrite("GET /1 HTTP/1.1\r\n"
21235 "Host: foo.test\r\n"
21236 "Connection: keep-alive\r\n\r\n")};
21237
21238 const MockRead kReads1[] = {
21239 MockRead("HTTP/1.1 200 OK\r\n"
21240 "Connection: close\r\n"
21241 "Content-Length: 1\r\n\r\n"
21242 "1")};
21243
21244 const MockWrite kWrites2[] = {
21245 MockWrite("GET /2 HTTP/1.1\r\n"
21246 "Host: foo.test\r\n"
21247 "Connection: keep-alive\r\n\r\n")};
21248
21249 const MockRead kReads2[] = {
21250 MockRead("HTTP/1.1 200 OK\r\n"
21251 "Connection: close\r\n"
21252 "Content-Length: 1\r\n\r\n"
21253 "2")};
21254
21255 const MockWrite kWrites3[] = {
21256 MockWrite("GET /3 HTTP/1.1\r\n"
21257 "Host: foo.test\r\n"
21258 "Connection: keep-alive\r\n\r\n")};
21259
21260 const MockRead kReads3[] = {
21261 MockRead("HTTP/1.1 200 OK\r\n"
21262 "Connection: close\r\n"
21263 "Content-Length: 1\r\n\r\n"
21264 "3")};
21265
21266 StaticSocketDataProvider data1(kReads1, kWrites1);
21267 StaticSocketDataProvider data2(kReads2, kWrites2);
21268 StaticSocketDataProvider data3(kReads3, kWrites3);
21269 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21270 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21271 session_deps_.socket_factory->AddSocketDataProvider(&data3);
21272
21273 SSLSocketDataProvider ssl_data1(ASYNC, OK);
21274 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
21275 ssl_data1.expected_network_isolation_key = kNetworkIsolationKey1;
21276 SSLSocketDataProvider ssl_data2(ASYNC, OK);
21277 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
21278 ssl_data2.expected_network_isolation_key = kNetworkIsolationKey2;
21279 SSLSocketDataProvider ssl_data3(ASYNC, OK);
21280 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
21281 ssl_data3.expected_network_isolation_key = kNetworkIsolationKey1;
21282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
21283 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
21284 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
21285
21286 TestCompletionCallback callback;
21287 HttpRequestInfo request1;
21288 request1.method = "GET";
21289 request1.url = GURL("https://foo.test/1");
21290 request1.traffic_annotation =
21291 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21292 request1.network_isolation_key = kNetworkIsolationKey1;
21293 auto trans1 =
21294 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21295 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21296 EXPECT_THAT(callback.GetResult(rv), IsOk());
21297 std::string response_data1;
21298 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21299 EXPECT_EQ("1", response_data1);
21300 trans1.reset();
21301
21302 HttpRequestInfo request2;
21303 request2.method = "GET";
21304 request2.url = GURL("https://foo.test/2");
21305 request2.traffic_annotation =
21306 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21307 request2.network_isolation_key = kNetworkIsolationKey2;
21308 auto trans2 =
21309 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21310 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21311 EXPECT_THAT(callback.GetResult(rv), IsOk());
21312 std::string response_data2;
21313 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21314 EXPECT_EQ("2", response_data2);
21315 trans2.reset();
21316
21317 HttpRequestInfo request3;
21318 request3.method = "GET";
21319 request3.url = GURL("https://foo.test/3");
21320 request3.traffic_annotation =
21321 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21322 request3.network_isolation_key = kNetworkIsolationKey1;
21323 auto trans3 =
21324 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21325 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21326 EXPECT_THAT(callback.GetResult(rv), IsOk());
21327 std::string response_data3;
21328 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21329 EXPECT_EQ("3", response_data3);
21330 trans3.reset();
21331}
21332
21333// Test that the NetworkIsolationKey is passed down to SSLConfig so the session
21334// cache is isolated, for both origins and proxies.
21335TEST_F(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
21336 base::test::ScopedFeatureList feature_list;
21337 feature_list.InitWithFeatures(
21338 {features::kPartitionConnectionsByNetworkIsolationKey,
21339 features::kPartitionSSLSessionsByNetworkIsolationKey},
21340 {});
21341
21342 session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
21343 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21344
21345 const NetworkIsolationKey kNetworkIsolationKey1(
21346 url::Origin::Create(GURL("http://origin1/")));
21347 const NetworkIsolationKey kNetworkIsolationKey2(
21348 url::Origin::Create(GURL("http://origin2/")));
21349 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21350
21351 // Make both a tunneled and non-tunneled request.
21352 HttpRequestInfo request1;
21353 request1.method = "GET";
21354 request1.url = GURL("https://foo.test/1");
21355 request1.traffic_annotation =
21356 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21357 request1.network_isolation_key = kNetworkIsolationKey1;
21358
21359 HttpRequestInfo request2;
21360 request2.method = "GET";
21361 request2.url = GURL("http://foo.test/2");
21362 request2.traffic_annotation =
21363 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21364 request2.network_isolation_key = kNetworkIsolationKey2;
21365
21366 const MockWrite kWrites1[] = {
21367 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
21368 "Host: foo.test:443\r\n"
21369 "Proxy-Connection: keep-alive\r\n\r\n"),
21370 MockWrite("GET /1 HTTP/1.1\r\n"
21371 "Host: foo.test\r\n"
21372 "Connection: keep-alive\r\n\r\n")};
21373
21374 const MockRead kReads1[] = {
21375 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
21376 MockRead("HTTP/1.1 200 OK\r\n"
21377 "Connection: close\r\n"
21378 "Content-Length: 1\r\n\r\n"
21379 "1")};
21380
21381 const MockWrite kWrites2[] = {
21382 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
21383 "Host: foo.test\r\n"
21384 "Proxy-Connection: keep-alive\r\n\r\n")};
21385
21386 const MockRead kReads2[] = {
21387 MockRead("HTTP/1.1 200 OK\r\n"
21388 "Connection: close\r\n"
21389 "Content-Length: 1\r\n\r\n"
21390 "2")};
21391
21392 StaticSocketDataProvider data1(kReads1, kWrites1);
21393 StaticSocketDataProvider data2(kReads2, kWrites2);
21394 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21395 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21396 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21397
21398 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
21399 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
21400 ssl_proxy1.expected_network_isolation_key = kNetworkIsolationKey1;
21401 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
21402 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
21403 ssl_origin1.expected_network_isolation_key = kNetworkIsolationKey1;
21404 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
21405 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
21406 ssl_proxy2.expected_network_isolation_key = kNetworkIsolationKey2;
21407 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
21408 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
21409 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
21410
21411 TestCompletionCallback callback;
21412 auto trans1 =
21413 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21414 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21415 EXPECT_THAT(callback.GetResult(rv), IsOk());
21416 std::string response_data1;
21417 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21418 EXPECT_EQ("1", response_data1);
21419 trans1.reset();
21420
21421 auto trans2 =
21422 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21423 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21424 EXPECT_THAT(callback.GetResult(rv), IsOk());
21425 std::string response_data2;
21426 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21427 EXPECT_EQ("2", response_data2);
21428 trans2.reset();
21429}
21430
David Benjaminef2f2a5a2019-07-16 19:21:3121431// Test that SSLConfig changes from SSLConfigService are picked up even when
21432// there are live sockets.
21433TEST_F(HttpNetworkTransactionTest, SSLConfigChanged) {
21434 SSLConfig ssl_config;
21435 ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21436 auto ssl_config_service = std::make_unique<TestSSLConfigService>(ssl_config);
21437 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21438
21439 session_deps_.ssl_config_service = std::move(ssl_config_service);
21440
21441 // Make three requests. Between the second and third, the SSL config will
21442 // change.
21443 HttpRequestInfo request1;
21444 request1.method = "GET";
21445 request1.url = GURL("https://foo.test/1");
21446 request1.traffic_annotation =
21447 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21448
21449 HttpRequestInfo request2;
21450 request2.method = "GET";
21451 request2.url = GURL("https://foo.test/2");
21452 request2.traffic_annotation =
21453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21454
21455 HttpRequestInfo request3;
21456 request3.method = "GET";
21457 request3.url = GURL("https://foo.test/3");
21458 request3.traffic_annotation =
21459 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21460
21461 const MockWrite kWrites1[] = {
21462 MockWrite("GET /1 HTTP/1.1\r\n"
21463 "Host: foo.test\r\n"
21464 "Connection: keep-alive\r\n\r\n"),
21465 MockWrite("GET /2 HTTP/1.1\r\n"
21466 "Host: foo.test\r\n"
21467 "Connection: keep-alive\r\n\r\n"),
21468 };
21469
21470 const MockRead kReads1[] = {
21471 MockRead("HTTP/1.1 200 OK\r\n"
21472 "Connection: keep-alive\r\n"
21473 "Content-Length: 1\r\n\r\n"
21474 "1"),
21475 MockRead("HTTP/1.1 200 OK\r\n"
21476 "Connection: keep-alive\r\n"
21477 "Content-Length: 1\r\n\r\n"
21478 "2"),
21479 };
21480
21481 // The third request goes on a different socket because the SSL config has
21482 // changed.
21483 const MockWrite kWrites2[] = {
21484 MockWrite("GET /3 HTTP/1.1\r\n"
21485 "Host: foo.test\r\n"
21486 "Connection: keep-alive\r\n\r\n")};
21487
21488 const MockRead kReads2[] = {
21489 MockRead("HTTP/1.1 200 OK\r\n"
21490 "Connection: keep-alive\r\n"
21491 "Content-Length: 1\r\n\r\n"
21492 "3")};
21493
21494 StaticSocketDataProvider data1(kReads1, kWrites1);
21495 StaticSocketDataProvider data2(kReads2, kWrites2);
21496 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21497 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21498
21499 SSLSocketDataProvider ssl1(ASYNC, OK);
21500 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21501 SSLSocketDataProvider ssl2(ASYNC, OK);
21502 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21503 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21505
21506 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21507
21508 TestCompletionCallback callback;
21509 auto trans1 =
21510 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21511 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
21512 EXPECT_THAT(callback.GetResult(rv), IsOk());
21513 std::string response_data1;
21514 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
21515 EXPECT_EQ("1", response_data1);
21516 trans1.reset();
21517
21518 auto trans2 =
21519 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21520 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
21521 EXPECT_THAT(callback.GetResult(rv), IsOk());
21522 std::string response_data2;
21523 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
21524 EXPECT_EQ("2", response_data2);
21525 trans2.reset();
21526
21527 ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21528 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_config);
21529
21530 auto trans3 =
21531 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21532 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
21533 EXPECT_THAT(callback.GetResult(rv), IsOk());
21534 std::string response_data3;
21535 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
21536 EXPECT_EQ("3", response_data3);
21537 trans3.reset();
21538}
21539
21540TEST_F(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
21541 SSLConfig ssl_config;
21542 ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21543 auto ssl_config_service = std::make_unique<TestSSLConfigService>(ssl_config);
21544 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
21545
21546 session_deps_.ssl_config_service = std::move(ssl_config_service);
21547
21548 HttpRequestInfo request;
21549 request.method = "GET";
21550 request.url = GURL("https://foo.test/1");
21551 request.traffic_annotation =
21552 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21553
21554 // Make a socket which never connects.
21555 StaticSocketDataProvider data({}, {});
21556 session_deps_.socket_factory->AddSocketDataProvider(&data);
21557 SSLSocketDataProvider ssl_data(SYNCHRONOUS, ERR_IO_PENDING);
21558 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
21559 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
21560
21561 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21562
21563 TestCompletionCallback callback;
21564 auto trans =
21565 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21566 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
21567 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21568
21569 ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
21570 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_config);
21571
21572 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NETWORK_CHANGED));
21573}
21574
[email protected]89ceba9a2009-03-21 03:46:0621575} // namespace net