blob: 38afa2536695f40cbc68d4b8ef2c4626ef7cc40b [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>
danakj1fd259a02016-04-16 03:17:0912#include <memory>
[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
[email protected]68bf9152008-09-25 19:47:3017#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5218#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2919#include "base/files/file_util.h"
[email protected]f3da152d2012-06-02 01:00:5720#include "base/json/json_writer.h"
Adam Rice425cf122015-01-19 06:18:2421#include "base/logging.h"
Avi Drissman13fc8932015-12-20 04:40:4622#include "base/macros.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"
[email protected]a34f61ee2014-03-18 20:59:4925#include "base/run_loop.h"
[email protected]125ef482013-06-11 18:32:4726#include "base/strings/string_util.h"
[email protected]750b2f3c2013-06-07 18:41:0527#include "base/strings/utf_string_conversions.h"
[email protected]f36a8132011-09-02 18:36:3328#include "base/test/test_file_util.h"
gabf767595f2016-05-11 18:50:3529#include "base/threading/thread_task_runner_handle.h"
[email protected]277d5942010-08-11 21:02:3530#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0731#include "net/base/chunked_upload_data_stream.h"
[email protected]bacff652009-03-31 17:50:3332#include "net/base/completion_callback.h"
mmenkecbc2b712014-10-09 20:29:0733#include "net/base/elements_upload_data_stream.h"
[email protected]58e32bb2013-01-21 18:23:2534#include "net/base/load_timing_info.h"
35#include "net/base/load_timing_info_test_util.h"
Adam Rice425cf122015-01-19 06:18:2436#include "net/base/net_errors.h"
tbansal28e68f82016-02-04 02:56:1537#include "net/base/proxy_delegate.h"
[email protected]ac790b42009-12-02 04:31:3138#include "net/base/request_priority.h"
initial.commit586acc5fe2008-07-26 22:42:5239#include "net/base/test_completion_callback.h"
tbansal28e68f82016-02-04 02:56:1540#include "net/base/test_proxy_delegate.h"
[email protected]b2d26cfd2012-12-11 10:36:0641#include "net/base/upload_bytes_element_reader.h"
[email protected]d98961652012-09-11 20:27:2142#include "net/base/upload_file_element_reader.h"
[email protected]6e7845ae2013-03-29 21:48:1143#include "net/cert/mock_cert_verifier.h"
[email protected]bc71b8772013-04-10 20:55:1644#include "net/dns/host_cache.h"
[email protected]f2cb3cf2013-03-21 01:40:5345#include "net/dns/mock_host_resolver.h"
[email protected]df41d0d82014-03-13 00:43:2446#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]3c32c5f2010-05-18 15:18:1247#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0048#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2949#include "net/http/http_auth_handler_ntlm.h"
aberentbba302d2015-12-03 10:20:1950#include "net/http/http_auth_scheme.h"
Adam Rice425cf122015-01-19 06:18:2451#include "net/http/http_basic_state.h"
[email protected]0877e3d2009-10-17 22:29:5752#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5253#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5654#include "net/http/http_network_session_peer.h"
Adam Rice425cf122015-01-19 06:18:2455#include "net/http/http_request_headers.h"
mmenke5f94fda2016-06-02 20:54:1356#include "net/http/http_response_info.h"
[email protected]17291a022011-10-10 07:32:5357#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5758#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3859#include "net/http/http_stream_factory.h"
Adam Rice425cf122015-01-19 06:18:2460#include "net/http/http_stream_parser.h"
[email protected]c41737d2014-05-14 07:47:1961#include "net/http/http_transaction_test_util.h"
eroman87c53d62015-04-02 06:51:0762#include "net/log/net_log.h"
vishal.b62985ca92015-04-17 08:45:5163#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4664#include "net/log/test_net_log_entry.h"
65#include "net/log/test_net_log_util.h"
sammc5dd160c2015-04-02 02:43:1366#include "net/proxy/mock_proxy_resolver.h"
[email protected]51fff29d2008-12-19 22:17:5367#include "net/proxy/proxy_config_service_fixed.h"
[email protected]e86839fd2013-08-14 18:29:0368#include "net/proxy/proxy_info.h"
[email protected]631f1322010-04-30 17:59:1169#include "net/proxy/proxy_resolver.h"
tbansal28e68f82016-02-04 02:56:1570#include "net/proxy/proxy_server.h"
[email protected]631f1322010-04-30 17:59:1171#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4472#include "net/socket/client_socket_factory.h"
mmenked3641e12016-01-28 16:06:1573#include "net/socket/client_socket_pool.h"
[email protected]483fa202013-05-14 01:07:0374#include "net/socket/client_socket_pool_manager.h"
ttuttle1f2d7e92015-04-28 16:17:4775#include "net/socket/connection_attempts.h"
[email protected]a42dbd142011-11-17 16:42:0276#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]bb88e1d32013-05-03 23:11:0777#include "net/socket/next_proto.h"
[email protected]f7984fc62009-06-22 23:26:4478#include "net/socket/socket_test_util.h"
79#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5480#include "net/spdy/spdy_framer.h"
81#include "net/spdy/spdy_session.h"
82#include "net/spdy/spdy_session_pool.h"
[email protected]23e482282013-06-14 16:08:0283#include "net/spdy/spdy_test_util_common.h"
nharperb7441ef2016-01-25 23:54:1484#include "net/ssl/default_channel_id_store.h"
[email protected]536fd0b2013-03-14 17:41:5785#include "net/ssl/ssl_cert_request_info.h"
[email protected]e86839fd2013-08-14 18:29:0386#include "net/ssl/ssl_config_service.h"
[email protected]536fd0b2013-03-14 17:41:5787#include "net/ssl/ssl_config_service_defaults.h"
88#include "net/ssl/ssl_info.h"
svaldez7872fd02015-11-19 21:10:5489#include "net/ssl/ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:1190#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0191#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4392#include "net/test/test_data_directory.h"
[email protected]831e4a32013-11-14 02:14:4493#include "net/websockets/websocket_handshake_stream_base.h"
bncf4588402015-11-24 13:33:1894#include "testing/gmock/include/gmock/gmock.h"
initial.commit586acc5fe2008-07-26 22:42:5295#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1596#include "testing/platform_test.h"
[email protected]795cbf82013-07-22 09:37:2797#include "url/gurl.h"
initial.commit586acc5fe2008-07-26 22:42:5298
robpercival214763f2016-07-01 23:27:0199using net::test::IsError;
100using net::test::IsOk;
101
[email protected]ad65a3e2013-12-25 18:18:01102using base::ASCIIToUTF16;
103
initial.commit586acc5fe2008-07-26 22:42:52104//-----------------------------------------------------------------------------
105
ttuttle859dc7a2015-04-23 19:42:29106namespace net {
107
[email protected]13c8a092010-07-29 06:15:44108namespace {
109
[email protected]42cba2fb2013-03-29 19:58:57110const base::string16 kBar(ASCIIToUTF16("bar"));
111const base::string16 kBar2(ASCIIToUTF16("bar2"));
112const base::string16 kBar3(ASCIIToUTF16("bar3"));
113const base::string16 kBaz(ASCIIToUTF16("baz"));
114const base::string16 kFirst(ASCIIToUTF16("first"));
115const base::string16 kFoo(ASCIIToUTF16("foo"));
116const base::string16 kFoo2(ASCIIToUTF16("foo2"));
117const base::string16 kFoo3(ASCIIToUTF16("foo3"));
118const base::string16 kFou(ASCIIToUTF16("fou"));
119const base::string16 kSecond(ASCIIToUTF16("second"));
120const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
121const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
[email protected]13c8a092010-07-29 06:15:44122
bnc2df4b522016-07-08 18:17:43123const char kAlternativeServiceHttpHeader[] =
124 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
125
ttuttle859dc7a2015-04-23 19:42:29126int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
127 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
128 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02129}
130
ttuttle859dc7a2015-04-23 19:42:29131int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) {
132 return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
133 ->IdleSocketCount();
[email protected]e5c026642012-03-17 00:14:02134}
135
ttuttle859dc7a2015-04-23 19:42:29136bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
137 return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)
138 ->IsStalled();
[email protected]043b68c82013-08-22 23:41:52139}
140
[email protected]f3da152d2012-06-02 01:00:57141// Takes in a Value created from a NetLogHttpResponseParameter, and returns
142// a JSONified list of headers as a single string. Uses single quotes instead
143// of double quotes for easier comparison. Returns false on failure.
[email protected]ea5ef4c2013-06-13 22:50:27144bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
[email protected]f3da152d2012-06-02 01:00:57145 if (!params)
146 return false;
[email protected]ea5ef4c2013-06-13 22:50:27147 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:57148 if (!params->GetList("headers", &header_list))
149 return false;
150 std::string double_quote_headers;
estade8d046462015-05-16 01:02:34151 base::JSONWriter::Write(*header_list, &double_quote_headers);
[email protected]466c9862013-12-03 22:05:28152 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
[email protected]f3da152d2012-06-02 01:00:57153 return true;
154}
155
[email protected]029c83b62013-01-24 05:28:20156// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
157// used.
ttuttle859dc7a2015-04-23 19:42:29158void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20159 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29160 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]58e32bb2013-01-21 18:23:25161
[email protected]029c83b62013-01-24 05:28:20162 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
163 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
164
ttuttle859dc7a2015-04-23 19:42:29165 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20166 EXPECT_FALSE(load_timing_info.send_start.is_null());
[email protected]58e32bb2013-01-21 18:23:25167
168 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]58e32bb2013-01-21 18:23:25169
[email protected]3b23a222013-05-15 21:33:25170 // Set at a higher level.
[email protected]58e32bb2013-01-21 18:23:25171 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
172 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25173 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25174}
175
[email protected]029c83b62013-01-24 05:28:20176// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
177// used.
ttuttle859dc7a2015-04-23 19:42:29178void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
[email protected]58e32bb2013-01-21 18:23:25179 int connect_timing_flags) {
[email protected]029c83b62013-01-24 05:28:20180 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29181 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20182
183 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
184 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
185
ttuttle859dc7a2015-04-23 19:42:29186 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
187 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20188 EXPECT_LE(load_timing_info.connect_timing.connect_end,
189 load_timing_info.send_start);
190
191 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20192
[email protected]3b23a222013-05-15 21:33:25193 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20194 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
195 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25196 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20197}
198
199// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
200// used.
ttuttle859dc7a2015-04-23 19:42:29201void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
[email protected]029c83b62013-01-24 05:28:20202 EXPECT_TRUE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29203 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20204
ttuttle859dc7a2015-04-23 19:42:29205 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
[email protected]029c83b62013-01-24 05:28:20206
207 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
208 EXPECT_LE(load_timing_info.proxy_resolve_start,
209 load_timing_info.proxy_resolve_end);
210 EXPECT_LE(load_timing_info.proxy_resolve_end,
211 load_timing_info.send_start);
212 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20213
[email protected]3b23a222013-05-15 21:33:25214 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20215 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
216 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25217 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]029c83b62013-01-24 05:28:20218}
219
220// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
221// used.
ttuttle859dc7a2015-04-23 19:42:29222void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
[email protected]029c83b62013-01-24 05:28:20223 int connect_timing_flags) {
224 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:29225 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:20226
227 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
228 EXPECT_LE(load_timing_info.proxy_resolve_start,
229 load_timing_info.proxy_resolve_end);
230 EXPECT_LE(load_timing_info.proxy_resolve_end,
231 load_timing_info.connect_timing.connect_start);
ttuttle859dc7a2015-04-23 19:42:29232 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
233 connect_timing_flags);
[email protected]029c83b62013-01-24 05:28:20234 EXPECT_LE(load_timing_info.connect_timing.connect_end,
235 load_timing_info.send_start);
236
237 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
[email protected]029c83b62013-01-24 05:28:20238
[email protected]3b23a222013-05-15 21:33:25239 // Set at a higher level.
[email protected]029c83b62013-01-24 05:28:20240 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
241 EXPECT_TRUE(load_timing_info.request_start.is_null());
[email protected]3b23a222013-05-15 21:33:25242 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]58e32bb2013-01-21 18:23:25243}
244
ttuttle859dc7a2015-04-23 19:42:29245void AddWebSocketHeaders(HttpRequestHeaders* headers) {
Adam Rice425cf122015-01-19 06:18:24246 headers->SetHeader("Connection", "Upgrade");
247 headers->SetHeader("Upgrade", "websocket");
bncce36dca22015-04-21 22:11:23248 headers->SetHeader("Origin", "http://www.example.org");
Adam Rice425cf122015-01-19 06:18:24249 headers->SetHeader("Sec-WebSocket-Version", "13");
250 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
251}
252
danakj1fd259a02016-04-16 03:17:09253std::unique_ptr<HttpNetworkSession> CreateSession(
mmenkee65e7af2015-10-13 17:16:42254 SpdySessionDependencies* session_deps) {
[email protected]c6bf8152012-12-02 07:43:34255 return SpdySessionDependencies::SpdyCreateSession(session_deps);
[email protected]e8d536192008-10-17 22:21:14256}
257
[email protected]448d4ca52012-03-04 04:12:23258} // namespace
259
bncd16676a2016-07-20 16:23:01260class HttpNetworkTransactionTest : public PlatformTest {
[email protected]483fa202013-05-14 01:07:03261 public:
bncd16676a2016-07-20 16:23:01262 ~HttpNetworkTransactionTest() override {
[email protected]483fa202013-05-14 01:07:03263 // Important to restore the per-pool limit first, since the pool limit must
264 // always be greater than group limit, and the tests reduce both limits.
265 ClientSocketPoolManager::set_max_sockets_per_pool(
266 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
267 ClientSocketPoolManager::set_max_sockets_per_group(
268 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
269 }
270
[email protected]e3ceb682011-06-28 23:55:46271 protected:
[email protected]23e482282013-06-14 16:08:02272 HttpNetworkTransactionTest()
bncd16676a2016-07-20 16:23:01273 : old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
[email protected]483fa202013-05-14 01:07:03274 HttpNetworkSession::NORMAL_SOCKET_POOL)),
275 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
276 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
bncb26024382016-06-29 02:39:45277 session_deps_.enable_http2_alternative_service_with_different_host = true;
[email protected]483fa202013-05-14 01:07:03278 }
[email protected]bb88e1d32013-05-03 23:11:07279
[email protected]e3ceb682011-06-28 23:55:46280 struct SimpleGetHelperResult {
281 int rv;
282 std::string status_line;
283 std::string response_data;
sclittlefb249892015-09-10 21:33:22284 int64_t total_received_bytes;
285 int64_t total_sent_bytes;
[email protected]58e32bb2013-01-21 18:23:25286 LoadTimingInfo load_timing_info;
ttuttle1f2d7e92015-04-28 16:17:47287 ConnectionAttempts connection_attempts;
ttuttled9dbc652015-09-29 20:00:59288 IPEndPoint remote_endpoint_after_start;
[email protected]e3ceb682011-06-28 23:55:46289 };
290
dcheng67be2b1f2014-10-27 21:47:29291 void SetUp() override {
[email protected]0b0bf032010-09-21 18:08:50292 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55293 base::RunLoop().RunUntilIdle();
[email protected]2ff8b312010-04-26 22:20:54294 }
295
dcheng67be2b1f2014-10-27 21:47:29296 void TearDown() override {
[email protected]0b0bf032010-09-21 18:08:50297 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55298 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09299 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:55300 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09301 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50302 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
fdoray92e35a72016-06-10 15:54:55303 base::RunLoop().RunUntilIdle();
[email protected]0e75a732008-10-16 20:36:09304 }
305
[email protected]202965992011-12-07 23:04:51306 // Either |write_failure| specifies a write failure or |read_failure|
307 // specifies a read failure when using a reused socket. In either case, the
308 // failure should cause the network transaction to resend the request, and the
309 // other argument should be NULL.
310 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
311 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52312
[email protected]a34f61ee2014-03-18 20:59:49313 // Either |write_failure| specifies a write failure or |read_failure|
314 // specifies a read failure when using a reused socket. In either case, the
315 // failure should cause the network transaction to resend the request, and the
316 // other argument should be NULL.
317 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:10318 const MockRead* read_failure,
319 bool use_spdy);
[email protected]a34f61ee2014-03-18 20:59:49320
[email protected]5a60c8b2011-10-19 20:14:29321 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
322 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15323 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52324
[email protected]ff007e162009-05-23 09:13:15325 HttpRequestInfo request;
326 request.method = "GET";
bncce36dca22015-04-21 22:11:23327 request.url = GURL("http://www.example.org/");
[email protected]ff007e162009-05-23 09:13:15328 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52329
vishal.b62985ca92015-04-17 08:45:51330 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:07331 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:09332 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
333 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41334 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:27335
[email protected]5a60c8b2011-10-19 20:14:29336 for (size_t i = 0; i < data_count; ++i) {
[email protected]bb88e1d32013-05-03 23:11:07337 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
[email protected]5a60c8b2011-10-19 20:14:29338 }
initial.commit586acc5fe2008-07-26 22:42:52339
[email protected]49639fa2011-12-20 23:22:41340 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52341
eroman24bc6a12015-05-06 19:55:48342 EXPECT_TRUE(log.bound().IsCapturing());
[email protected]49639fa2011-12-20 23:22:41343 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:01344 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:52345
[email protected]ff007e162009-05-23 09:13:15346 out.rv = callback.WaitForResult();
sclittlefb249892015-09-10 21:33:22347 out.total_received_bytes = trans->GetTotalReceivedBytes();
348 out.total_sent_bytes = trans->GetTotalSentBytes();
[email protected]58e32bb2013-01-21 18:23:25349
350 // Even in the failure cases that use this function, connections are always
351 // successfully established before the error.
352 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
353 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
354
[email protected]ff007e162009-05-23 09:13:15355 if (out.rv != OK)
356 return out;
357
358 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50359 // Can't use ASSERT_* inside helper functions like this, so
360 // return an error.
wezca1070932016-05-26 20:30:52361 if (!response || !response->headers) {
[email protected]fe2255a2011-09-20 19:37:50362 out.rv = ERR_UNEXPECTED;
363 return out;
364 }
[email protected]ff007e162009-05-23 09:13:15365 out.status_line = response->headers->GetStatusLine();
366
[email protected]80a09a82012-11-16 17:40:06367 EXPECT_EQ("127.0.0.1", response->socket_address.host());
368 EXPECT_EQ(80, response->socket_address.port());
[email protected]6d81b482011-02-22 19:47:19369
ttuttled9dbc652015-09-29 20:00:59370 bool got_endpoint =
371 trans->GetRemoteEndpoint(&out.remote_endpoint_after_start);
372 EXPECT_EQ(got_endpoint,
373 out.remote_endpoint_after_start.address().size() > 0);
374
[email protected]ff007e162009-05-23 09:13:15375 rv = ReadTransaction(trans.get(), &out.response_data);
robpercival214763f2016-07-01 23:27:01376 EXPECT_THAT(rv, IsOk());
[email protected]b2fcd0e2010-12-01 15:19:40377
mmenke43758e62015-05-04 21:09:46378 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:40379 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39380 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40381 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12382 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39383 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40384 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39385 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
386 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15387
[email protected]f3da152d2012-06-02 01:00:57388 std::string line;
389 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
390 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
391
[email protected]79e1fd62013-06-20 06:50:04392 HttpRequestHeaders request_headers;
393 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
394 std::string value;
395 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
bncce36dca22015-04-21 22:11:23396 EXPECT_EQ("www.example.org", value);
[email protected]79e1fd62013-06-20 06:50:04397 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
398 EXPECT_EQ("keep-alive", value);
399
400 std::string response_headers;
401 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
bncce36dca22015-04-21 22:11:23402 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
[email protected]79e1fd62013-06-20 06:50:04403 response_headers);
[email protected]3deb9a52010-11-11 00:24:40404
sclittlefb249892015-09-10 21:33:22405 out.total_received_bytes = trans->GetTotalReceivedBytes();
406 // The total number of sent bytes should not have changed.
407 EXPECT_EQ(out.total_sent_bytes, trans->GetTotalSentBytes());
408
ttuttle1f2d7e92015-04-28 16:17:47409 trans->GetConnectionAttempts(&out.connection_attempts);
[email protected]aecfbf22008-10-16 02:02:47410 return out;
[email protected]ff007e162009-05-23 09:13:15411 }
initial.commit586acc5fe2008-07-26 22:42:52412
[email protected]5a60c8b2011-10-19 20:14:29413 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
414 size_t reads_count) {
sclittlefb249892015-09-10 21:33:22415 MockWrite data_writes[] = {
416 MockWrite("GET / HTTP/1.1\r\n"
417 "Host: www.example.org\r\n"
418 "Connection: keep-alive\r\n\r\n"),
419 };
[email protected]5a60c8b2011-10-19 20:14:29420
sclittlefb249892015-09-10 21:33:22421 StaticSocketDataProvider reads(data_reads, reads_count, data_writes,
422 arraysize(data_writes));
423 StaticSocketDataProvider* data[] = {&reads};
424 SimpleGetHelperResult out = SimpleGetHelperForData(data, 1);
425
426 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
427 out.total_sent_bytes);
428 return out;
[email protected]b8015c42013-12-24 15:18:19429 }
430
[email protected]ff007e162009-05-23 09:13:15431 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
432 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52433
[email protected]ff007e162009-05-23 09:13:15434 void ConnectStatusHelper(const MockRead& status);
[email protected]bb88e1d32013-05-03 23:11:07435
436 void BypassHostCacheOnRefreshHelper(int load_flags);
437
438 void CheckErrorIsPassedBack(int error, IoMode mode);
439
[email protected]4bd46222013-05-14 19:32:23440 SpdyTestUtil spdy_util_;
[email protected]bb88e1d32013-05-03 23:11:07441 SpdySessionDependencies session_deps_;
[email protected]483fa202013-05-14 01:07:03442
443 // Original socket limits. Some tests set these. Safest to always restore
444 // them once each test has been run.
445 int old_max_group_sockets_;
446 int old_max_pool_sockets_;
[email protected]ff007e162009-05-23 09:13:15447};
[email protected]231d5a32008-09-13 00:45:27448
[email protected]448d4ca52012-03-04 04:12:23449namespace {
450
ryansturm49a8cb12016-06-15 16:51:09451class BeforeHeadersSentHandler {
[email protected]597a1ab2014-06-26 08:12:27452 public:
ryansturm49a8cb12016-06-15 16:51:09453 BeforeHeadersSentHandler()
454 : observed_before_headers_sent_with_proxy_(false),
455 observed_before_headers_sent_(false) {}
[email protected]597a1ab2014-06-26 08:12:27456
ryansturm49a8cb12016-06-15 16:51:09457 void OnBeforeHeadersSent(const ProxyInfo& proxy_info,
458 HttpRequestHeaders* request_headers) {
459 observed_before_headers_sent_ = true;
460 if (!proxy_info.is_http() && !proxy_info.is_https() &&
461 !proxy_info.is_quic()) {
462 return;
463 }
464 observed_before_headers_sent_with_proxy_ = true;
[email protected]597a1ab2014-06-26 08:12:27465 observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
466 }
467
ryansturm49a8cb12016-06-15 16:51:09468 bool observed_before_headers_sent_with_proxy() const {
469 return observed_before_headers_sent_with_proxy_;
470 }
471
472 bool observed_before_headers_sent() const {
473 return observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27474 }
475
476 std::string observed_proxy_server_uri() const {
477 return observed_proxy_server_uri_;
478 }
479
480 private:
ryansturm49a8cb12016-06-15 16:51:09481 bool observed_before_headers_sent_with_proxy_;
482 bool observed_before_headers_sent_;
[email protected]597a1ab2014-06-26 08:12:27483 std::string observed_proxy_server_uri_;
484
ryansturm49a8cb12016-06-15 16:51:09485 DISALLOW_COPY_AND_ASSIGN(BeforeHeadersSentHandler);
[email protected]597a1ab2014-06-26 08:12:27486};
487
[email protected]15a5ccf82008-10-23 19:57:43488// Fill |str| with a long header list that consumes >= |size| bytes.
489void FillLargeHeadersString(std::string* str, int size) {
thestig9d3bb0c2015-01-24 00:49:51490 const char row[] =
[email protected]4ddaf2502008-10-23 18:26:19491 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
492 const int sizeof_row = strlen(row);
493 const int num_rows = static_cast<int>(
494 ceil(static_cast<float>(size) / sizeof_row));
495 const int sizeof_data = num_rows * sizeof_row;
496 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43497 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51498
[email protected]4ddaf2502008-10-23 18:26:19499 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43500 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19501}
502
thakis84dff942015-07-28 20:47:38503#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29504// Alternative functions that eliminate randomness and dependency on the local
505// host name so that the generated NTLM messages are reproducible.
avibf0746c2015-12-09 19:53:14506void MockGenerateRandom1(uint8_t* output, size_t n) {
507 static const uint8_t bytes[] = {0x55, 0x29, 0x66, 0x26,
508 0x6b, 0x9c, 0x73, 0x54};
[email protected]385a4672009-03-11 22:21:29509 static size_t current_byte = 0;
510 for (size_t i = 0; i < n; ++i) {
511 output[i] = bytes[current_byte++];
512 current_byte %= arraysize(bytes);
513 }
514}
515
avibf0746c2015-12-09 19:53:14516void MockGenerateRandom2(uint8_t* output, size_t n) {
517 static const uint8_t bytes[] = {0x96, 0x79, 0x85, 0xe7, 0x49, 0x93,
518 0x70, 0xa1, 0x4e, 0xe7, 0x87, 0x45,
519 0x31, 0x5b, 0xd3, 0x1f};
[email protected]385a4672009-03-11 22:21:29520 static size_t current_byte = 0;
521 for (size_t i = 0; i < n; ++i) {
522 output[i] = bytes[current_byte++];
523 current_byte %= arraysize(bytes);
524 }
525}
526
[email protected]fe2bc6a2009-03-23 16:52:20527std::string MockGetHostName() {
528 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29529}
thakis84dff942015-07-28 20:47:38530#endif // defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:29531
[email protected]e60e47a2010-07-14 03:37:18532template<typename ParentPool>
533class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31534 public:
[email protected]9e1bdd32011-02-03 21:48:34535 CaptureGroupNameSocketPool(HostResolver* host_resolver,
536 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18537
[email protected]d80a4322009-08-14 07:07:49538 const std::string last_group_name_received() const {
539 return last_group_name_;
540 }
541
dmichaeld6e570d2014-12-18 22:30:57542 int RequestSocket(const std::string& group_name,
543 const void* socket_params,
544 RequestPriority priority,
mmenked3641e12016-01-28 16:06:15545 ClientSocketPool::RespectLimits respect_limits,
dmichaeld6e570d2014-12-18 22:30:57546 ClientSocketHandle* handle,
547 const CompletionCallback& callback,
548 const BoundNetLog& net_log) override {
[email protected]04e5be32009-06-26 20:00:31549 last_group_name_ = group_name;
550 return ERR_IO_PENDING;
551 }
dmichaeld6e570d2014-12-18 22:30:57552 void CancelRequest(const std::string& group_name,
553 ClientSocketHandle* handle) override {}
554 void ReleaseSocket(const std::string& group_name,
danakj1fd259a02016-04-16 03:17:09555 std::unique_ptr<StreamSocket> socket,
dmichaeld6e570d2014-12-18 22:30:57556 int id) override {}
557 void CloseIdleSockets() override {}
558 int IdleSocketCount() const override { return 0; }
559 int IdleSocketCountInGroup(const std::string& group_name) const override {
[email protected]04e5be32009-06-26 20:00:31560 return 0;
561 }
dmichaeld6e570d2014-12-18 22:30:57562 LoadState GetLoadState(const std::string& group_name,
563 const ClientSocketHandle* handle) const override {
[email protected]04e5be32009-06-26 20:00:31564 return LOAD_STATE_IDLE;
565 }
dmichaeld6e570d2014-12-18 22:30:57566 base::TimeDelta ConnectionTimeout() const override {
[email protected]a796bcec2010-03-22 17:17:26567 return base::TimeDelta();
568 }
[email protected]d80a4322009-08-14 07:07:49569
570 private:
[email protected]04e5be32009-06-26 20:00:31571 std::string last_group_name_;
572};
573
[email protected]ab739042011-04-07 15:22:28574typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
575CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13576typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
577CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06578typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11579CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18580typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
581CaptureGroupNameSSLSocketPool;
582
rkaplowd90695c2015-03-25 22:12:41583template <typename ParentPool>
[email protected]e60e47a2010-07-14 03:37:18584CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34585 HostResolver* host_resolver,
586 CertVerifier* /* cert_verifier */)
tbansal7b403bcc2016-04-13 22:33:21587 : ParentPool(0, 0, host_resolver, NULL, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18588
hashimoto0d3e4fb2015-01-09 05:02:50589template <>
[email protected]2df19bb2010-08-25 20:13:46590CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21591 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34592 CertVerifier* /* cert_verifier */)
rkaplowd90695c2015-03-25 22:12:41593 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL) {
hashimoto0d3e4fb2015-01-09 05:02:50594}
[email protected]2df19bb2010-08-25 20:13:46595
[email protected]007b3f82013-04-09 08:46:45596template <>
[email protected]e60e47a2010-07-14 03:37:18597CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
hashimotodae13b02015-01-15 04:28:21598 HostResolver* /* host_resolver */,
[email protected]9e1bdd32011-02-03 21:48:34599 CertVerifier* cert_verifier)
[email protected]007b3f82013-04-09 08:46:45600 : SSLClientSocketPool(0,
601 0,
[email protected]007b3f82013-04-09 08:46:45602 cert_verifier,
603 NULL,
604 NULL,
[email protected]284303b62013-11-28 15:11:54605 NULL,
eranm6571b2b2014-12-03 15:53:23606 NULL,
[email protected]007b3f82013-04-09 08:46:45607 std::string(),
608 NULL,
609 NULL,
610 NULL,
611 NULL,
612 NULL,
[email protected]8e458552014-08-05 00:02:15613 NULL) {
614}
[email protected]2227c692010-05-04 15:36:11615
[email protected]231d5a32008-09-13 00:45:27616//-----------------------------------------------------------------------------
617
[email protected]79cb5c12011-09-12 13:12:04618// Helper functions for validating that AuthChallengeInfo's are correctly
619// configured for common cases.
620bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
621 if (!auth_challenge)
622 return false;
623 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43624 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04625 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19626 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04627 return true;
628}
629
630bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
631 if (!auth_challenge)
632 return false;
633 EXPECT_TRUE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43634 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
635 EXPECT_EQ("MyRealm1", auth_challenge->realm);
636 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
637 return true;
638}
639
640bool CheckBasicSecureProxyAuth(const AuthChallengeInfo* auth_challenge) {
641 if (!auth_challenge)
642 return false;
643 EXPECT_TRUE(auth_challenge->is_proxy);
644 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04645 EXPECT_EQ("MyRealm1", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19646 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04647 return true;
648}
649
650bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
651 if (!auth_challenge)
652 return false;
653 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43654 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04655 EXPECT_EQ("digestive", auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19656 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04657 return true;
658}
659
thakis84dff942015-07-28 20:47:38660#if defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04661bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
662 if (!auth_challenge)
663 return false;
664 EXPECT_FALSE(auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:43665 EXPECT_EQ("http://172.22.68.17", auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:04666 EXPECT_EQ(std::string(), auth_challenge->realm);
aberentbba302d2015-12-03 10:20:19667 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
[email protected]79cb5c12011-09-12 13:12:04668 return true;
669}
thakis84dff942015-07-28 20:47:38670#endif // defined(NTLM_PORTABLE)
[email protected]79cb5c12011-09-12 13:12:04671
[email protected]448d4ca52012-03-04 04:12:23672} // namespace
673
bncd16676a2016-07-20 16:23:01674TEST_F(HttpNetworkTransactionTest, Basic) {
danakj1fd259a02016-04-16 03:17:09675 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
676 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41677 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]231d5a32008-09-13 00:45:27678}
679
bncd16676a2016-07-20 16:23:01680TEST_F(HttpNetworkTransactionTest, SimpleGET) {
[email protected]231d5a32008-09-13 00:45:27681 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35682 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
683 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06684 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27685 };
[email protected]31a2bfe2010-02-09 08:03:39686 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
687 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01688 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27689 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
690 EXPECT_EQ("hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22691 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
692 EXPECT_EQ(reads_size, out.total_received_bytes);
ttuttle1f2d7e92015-04-28 16:17:47693 EXPECT_EQ(0u, out.connection_attempts.size());
ttuttled9dbc652015-09-29 20:00:59694
695 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
[email protected]231d5a32008-09-13 00:45:27696}
697
698// Response with no status line.
bncd16676a2016-07-20 16:23:01699TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
[email protected]231d5a32008-09-13 00:45:27700 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35701 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:06702 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27703 };
[email protected]31a2bfe2010-02-09 08:03:39704 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
705 arraysize(data_reads));
mmenkee2172e42016-07-15 03:14:32706 EXPECT_THAT(out.rv, IsError(ERR_INVALID_HTTP_RESPONSE));
[email protected]231d5a32008-09-13 00:45:27707}
708
709// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01710TEST_F(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
[email protected]231d5a32008-09-13 00:45:27711 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35712 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06713 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27714 };
[email protected]31a2bfe2010-02-09 08:03:39715 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
716 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01717 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27718 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
719 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22720 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
721 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27722}
723
724// Allow up to 4 bytes of junk to precede status line.
bncd16676a2016-07-20 16:23:01725TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
[email protected]231d5a32008-09-13 00:45:27726 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35727 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06728 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27729 };
[email protected]31a2bfe2010-02-09 08:03:39730 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
731 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01732 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27733 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
734 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22735 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
736 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27737}
738
739// Beyond 4 bytes of slop and it should fail to find a status line.
bncd16676a2016-07-20 16:23:01740TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
[email protected]231d5a32008-09-13 00:45:27741 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35742 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]8ddf8322012-02-23 18:08:06743 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27744 };
[email protected]31a2bfe2010-02-09 08:03:39745 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
746 arraysize(data_reads));
mmenkee2172e42016-07-15 03:14:32747 EXPECT_THAT(out.rv, IsError(ERR_INVALID_HTTP_RESPONSE));
[email protected]231d5a32008-09-13 00:45:27748}
749
750// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
bncd16676a2016-07-20 16:23:01751TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
[email protected]231d5a32008-09-13 00:45:27752 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35753 MockRead("\n"),
754 MockRead("\n"),
755 MockRead("Q"),
756 MockRead("J"),
757 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]8ddf8322012-02-23 18:08:06758 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27759 };
[email protected]31a2bfe2010-02-09 08:03:39760 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
761 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01762 EXPECT_THAT(out.rv, IsOk());
[email protected]231d5a32008-09-13 00:45:27763 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
764 EXPECT_EQ("DATA", out.response_data);
sclittlefb249892015-09-10 21:33:22765 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
766 EXPECT_EQ(reads_size, out.total_received_bytes);
[email protected]231d5a32008-09-13 00:45:27767}
768
769// Close the connection before enough bytes to have a status line.
bncd16676a2016-07-20 16:23:01770TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
[email protected]231d5a32008-09-13 00:45:27771 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35772 MockRead("HTT"),
[email protected]8ddf8322012-02-23 18:08:06773 MockRead(SYNCHRONOUS, OK),
[email protected]231d5a32008-09-13 00:45:27774 };
[email protected]31a2bfe2010-02-09 08:03:39775 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
776 arraysize(data_reads));
mmenkee2172e42016-07-15 03:14:32777 EXPECT_THAT(out.rv, IsError(ERR_INVALID_HTTP_RESPONSE));
initial.commit586acc5fe2008-07-26 22:42:52778}
779
[email protected]f9d44aa2008-09-23 23:57:17780// Simulate a 204 response, lacking a Content-Length header, sent over a
781// persistent connection. The response should still terminate since a 204
782// cannot have a response body.
bncd16676a2016-07-20 16:23:01783TEST_F(HttpNetworkTransactionTest, StopsReading204) {
[email protected]b8015c42013-12-24 15:18:19784 char junk[] = "junk";
[email protected]f9d44aa2008-09-23 23:57:17785 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35786 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
[email protected]b8015c42013-12-24 15:18:19787 MockRead(junk), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:06788 MockRead(SYNCHRONOUS, OK),
[email protected]f9d44aa2008-09-23 23:57:17789 };
[email protected]31a2bfe2010-02-09 08:03:39790 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
791 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01792 EXPECT_THAT(out.rv, IsOk());
[email protected]f9d44aa2008-09-23 23:57:17793 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
794 EXPECT_EQ("", out.response_data);
sclittlefb249892015-09-10 21:33:22795 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
796 int64_t response_size = reads_size - strlen(junk);
797 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]f9d44aa2008-09-23 23:57:17798}
799
[email protected]0877e3d2009-10-17 22:29:57800// A simple request using chunked encoding with some extra data after.
bncd16676a2016-07-20 16:23:01801TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
[email protected]b8015c42013-12-24 15:18:19802 std::string final_chunk = "0\r\n\r\n";
803 std::string extra_data = "HTTP/1.1 200 OK\r\n";
804 std::string last_read = final_chunk + extra_data;
[email protected]0877e3d2009-10-17 22:29:57805 MockRead data_reads[] = {
806 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
807 MockRead("5\r\nHello\r\n"),
808 MockRead("1\r\n"),
809 MockRead(" \r\n"),
810 MockRead("5\r\nworld\r\n"),
[email protected]b8015c42013-12-24 15:18:19811 MockRead(last_read.data()),
[email protected]8ddf8322012-02-23 18:08:06812 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57813 };
[email protected]31a2bfe2010-02-09 08:03:39814 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
815 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01816 EXPECT_THAT(out.rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:57817 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
818 EXPECT_EQ("Hello world", out.response_data);
sclittlefb249892015-09-10 21:33:22819 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
820 int64_t response_size = reads_size - extra_data.size();
821 EXPECT_EQ(response_size, out.total_received_bytes);
[email protected]0877e3d2009-10-17 22:29:57822}
823
[email protected]9fe44f52010-09-23 18:36:00824// Next tests deal with http://crbug.com/56344.
825
bncd16676a2016-07-20 16:23:01826TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00827 MultipleContentLengthHeadersNoTransferEncoding) {
828 MockRead data_reads[] = {
829 MockRead("HTTP/1.1 200 OK\r\n"),
830 MockRead("Content-Length: 10\r\n"),
831 MockRead("Content-Length: 5\r\n\r\n"),
832 };
833 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
834 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01835 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]9fe44f52010-09-23 18:36:00836}
837
bncd16676a2016-07-20 16:23:01838TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04839 DuplicateContentLengthHeadersNoTransferEncoding) {
840 MockRead data_reads[] = {
841 MockRead("HTTP/1.1 200 OK\r\n"),
842 MockRead("Content-Length: 5\r\n"),
843 MockRead("Content-Length: 5\r\n\r\n"),
844 MockRead("Hello"),
845 };
846 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
847 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01848 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:04849 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
850 EXPECT_EQ("Hello", out.response_data);
851}
852
bncd16676a2016-07-20 16:23:01853TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04854 ComplexContentLengthHeadersNoTransferEncoding) {
855 // More than 2 dupes.
856 {
857 MockRead data_reads[] = {
858 MockRead("HTTP/1.1 200 OK\r\n"),
859 MockRead("Content-Length: 5\r\n"),
860 MockRead("Content-Length: 5\r\n"),
861 MockRead("Content-Length: 5\r\n\r\n"),
862 MockRead("Hello"),
863 };
864 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
865 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01866 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:04867 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
868 EXPECT_EQ("Hello", out.response_data);
869 }
870 // HTTP/1.0
871 {
872 MockRead data_reads[] = {
873 MockRead("HTTP/1.0 200 OK\r\n"),
874 MockRead("Content-Length: 5\r\n"),
875 MockRead("Content-Length: 5\r\n"),
876 MockRead("Content-Length: 5\r\n\r\n"),
877 MockRead("Hello"),
878 };
879 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
880 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01881 EXPECT_THAT(out.rv, IsOk());
[email protected]44b52042010-10-29 22:48:04882 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
883 EXPECT_EQ("Hello", out.response_data);
884 }
885 // 2 dupes and one mismatched.
886 {
887 MockRead data_reads[] = {
888 MockRead("HTTP/1.1 200 OK\r\n"),
889 MockRead("Content-Length: 10\r\n"),
890 MockRead("Content-Length: 10\r\n"),
891 MockRead("Content-Length: 5\r\n\r\n"),
892 };
893 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
894 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01895 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
[email protected]44b52042010-10-29 22:48:04896 }
897}
898
bncd16676a2016-07-20 16:23:01899TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00900 MultipleContentLengthHeadersTransferEncoding) {
901 MockRead data_reads[] = {
902 MockRead("HTTP/1.1 200 OK\r\n"),
903 MockRead("Content-Length: 666\r\n"),
904 MockRead("Content-Length: 1337\r\n"),
905 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
906 MockRead("5\r\nHello\r\n"),
907 MockRead("1\r\n"),
908 MockRead(" \r\n"),
909 MockRead("5\r\nworld\r\n"),
910 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:06911 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:00912 };
913 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
914 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01915 EXPECT_THAT(out.rv, IsOk());
[email protected]9fe44f52010-09-23 18:36:00916 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
917 EXPECT_EQ("Hello world", out.response_data);
918}
919
[email protected]1628fe92011-10-04 23:04:55920// Next tests deal with http://crbug.com/98895.
921
922// Checks that a single Content-Disposition header results in no error.
bncd16676a2016-07-20 16:23:01923TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
[email protected]1628fe92011-10-04 23:04:55924 MockRead data_reads[] = {
925 MockRead("HTTP/1.1 200 OK\r\n"),
926 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
927 MockRead("Content-Length: 5\r\n\r\n"),
928 MockRead("Hello"),
929 };
930 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
931 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01932 EXPECT_THAT(out.rv, IsOk());
[email protected]1628fe92011-10-04 23:04:55933 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
934 EXPECT_EQ("Hello", out.response_data);
935}
936
[email protected]54a9c6e52012-03-21 20:10:59937// Checks that two identical Content-Disposition headers result in no error.
bncd16676a2016-07-20 16:23:01938TEST_F(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55939 MockRead data_reads[] = {
940 MockRead("HTTP/1.1 200 OK\r\n"),
941 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
942 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
943 MockRead("Content-Length: 5\r\n\r\n"),
944 MockRead("Hello"),
945 };
946 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
947 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01948 EXPECT_THAT(out.rv, IsOk());
[email protected]54a9c6e52012-03-21 20:10:59949 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
950 EXPECT_EQ("Hello", out.response_data);
[email protected]1628fe92011-10-04 23:04:55951}
952
953// Checks that two distinct Content-Disposition headers result in an error.
bncd16676a2016-07-20 16:23:01954TEST_F(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
[email protected]1628fe92011-10-04 23:04:55955 MockRead data_reads[] = {
956 MockRead("HTTP/1.1 200 OK\r\n"),
957 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
958 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
959 MockRead("Content-Length: 5\r\n\r\n"),
960 MockRead("Hello"),
961 };
962 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
963 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:01964 EXPECT_THAT(out.rv,
965 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
[email protected]1628fe92011-10-04 23:04:55966}
967
[email protected]54a9c6e52012-03-21 20:10:59968// Checks that two identical Location headers result in no error.
969// Also tests Location header behavior.
bncd16676a2016-07-20 16:23:01970TEST_F(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:55971 MockRead data_reads[] = {
972 MockRead("HTTP/1.1 302 Redirect\r\n"),
973 MockRead("Location: http://good.com/\r\n"),
[email protected]54a9c6e52012-03-21 20:10:59974 MockRead("Location: http://good.com/\r\n"),
[email protected]1628fe92011-10-04 23:04:55975 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:06976 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:55977 };
978
979 HttpRequestInfo request;
980 request.method = "GET";
981 request.url = GURL("http://redirect.com/");
982 request.load_flags = 0;
983
danakj1fd259a02016-04-16 03:17:09984 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
985 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:41986 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]1628fe92011-10-04 23:04:55987
988 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:07989 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1628fe92011-10-04 23:04:55990
[email protected]49639fa2011-12-20 23:22:41991 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:55992
[email protected]49639fa2011-12-20 23:22:41993 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:01994 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1628fe92011-10-04 23:04:55995
robpercival214763f2016-07-01 23:27:01996 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]1628fe92011-10-04 23:04:55997
998 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:52999 ASSERT_TRUE(response);
1000 ASSERT_TRUE(response->headers);
[email protected]1628fe92011-10-04 23:04:551001 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1002 std::string url;
1003 EXPECT_TRUE(response->headers->IsRedirect(&url));
1004 EXPECT_EQ("http://good.com/", url);
[email protected]d8fc4722014-06-13 13:17:151005 EXPECT_TRUE(response->proxy_server.IsEmpty());
[email protected]1628fe92011-10-04 23:04:551006}
1007
[email protected]1628fe92011-10-04 23:04:551008// Checks that two distinct Location headers result in an error.
bncd16676a2016-07-20 16:23:011009TEST_F(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
[email protected]1628fe92011-10-04 23:04:551010 MockRead data_reads[] = {
1011 MockRead("HTTP/1.1 302 Redirect\r\n"),
1012 MockRead("Location: http://good.com/\r\n"),
1013 MockRead("Location: http://evil.com/\r\n"),
1014 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:061015 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:551016 };
1017 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1018 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:011019 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
[email protected]1628fe92011-10-04 23:04:551020}
1021
[email protected]ef0faf2e72009-03-05 23:27:231022// Do a request using the HEAD method. Verify that we don't try to read the
1023// message body (since HEAD has none).
bncd16676a2016-07-20 16:23:011024TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:421025 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:231026 request.method = "HEAD";
bncce36dca22015-04-21 22:11:231027 request.url = GURL("http://www.example.org/");
[email protected]ef0faf2e72009-03-05 23:27:231028 request.load_flags = 0;
1029
danakj1fd259a02016-04-16 03:17:091030 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1031 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411032 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ryansturm49a8cb12016-06-15 16:51:091033 BeforeHeadersSentHandler headers_handler;
1034 trans->SetBeforeHeadersSentCallback(
1035 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
1036 base::Unretained(&headers_handler)));
[email protected]cb9bf6ca2011-01-28 13:15:271037
[email protected]ef0faf2e72009-03-05 23:27:231038 MockWrite data_writes1[] = {
csharrisonf473dd192015-08-18 13:54:131039 MockWrite("HEAD / HTTP/1.1\r\n"
1040 "Host: www.example.org\r\n"
1041 "Connection: keep-alive\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231042 };
1043 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:231044 MockRead("HTTP/1.1 404 Not Found\r\n"), MockRead("Server: Blah\r\n"),
1045 MockRead("Content-Length: 1234\r\n\r\n"),
[email protected]ef0faf2e72009-03-05 23:27:231046
mmenked39192ee2015-12-09 00:57:231047 // No response body because the test stops reading here.
1048 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]ef0faf2e72009-03-05 23:27:231049 };
1050
[email protected]31a2bfe2010-02-09 08:03:391051 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1052 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:071053 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:231054
[email protected]49639fa2011-12-20 23:22:411055 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:231056
[email protected]49639fa2011-12-20 23:22:411057 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011058 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ef0faf2e72009-03-05 23:27:231059
1060 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:011061 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231062
[email protected]1c773ea12009-04-28 19:58:421063 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521064 ASSERT_TRUE(response);
[email protected]ef0faf2e72009-03-05 23:27:231065
1066 // Check that the headers got parsed.
wezca1070932016-05-26 20:30:521067 EXPECT_TRUE(response->headers);
[email protected]ef0faf2e72009-03-05 23:27:231068 EXPECT_EQ(1234, response->headers->GetContentLength());
1069 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151070 EXPECT_TRUE(response->proxy_server.IsEmpty());
ryansturm49a8cb12016-06-15 16:51:091071 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
1072 EXPECT_FALSE(headers_handler.observed_before_headers_sent_with_proxy());
[email protected]ef0faf2e72009-03-05 23:27:231073
1074 std::string server_header;
olli.raulaee489a52016-01-25 08:37:101075 size_t iter = 0;
[email protected]ef0faf2e72009-03-05 23:27:231076 bool has_server_header = response->headers->EnumerateHeader(
1077 &iter, "Server", &server_header);
1078 EXPECT_TRUE(has_server_header);
1079 EXPECT_EQ("Blah", server_header);
1080
1081 // Reading should give EOF right away, since there is no message body
1082 // (despite non-zero content-length).
1083 std::string response_data;
1084 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011085 EXPECT_THAT(rv, IsOk());
[email protected]ef0faf2e72009-03-05 23:27:231086 EXPECT_EQ("", response_data);
1087}
1088
bncd16676a2016-07-20 16:23:011089TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
danakj1fd259a02016-04-16 03:17:091090 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
initial.commit586acc5fe2008-07-26 22:42:521091
1092 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351093 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1094 MockRead("hello"),
1095 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1096 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061097 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521098 };
[email protected]31a2bfe2010-02-09 08:03:391099 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071100 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521101
[email protected]0b0bf032010-09-21 18:08:501102 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521103 "hello", "world"
1104 };
1105
1106 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:421107 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521108 request.method = "GET";
bncce36dca22015-04-21 22:11:231109 request.url = GURL("http://www.example.org/");
initial.commit586acc5fe2008-07-26 22:42:521110 request.load_flags = 0;
1111
danakj1fd259a02016-04-16 03:17:091112 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501113 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271114
[email protected]49639fa2011-12-20 23:22:411115 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521116
[email protected]49639fa2011-12-20 23:22:411117 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521119
1120 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011121 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521122
[email protected]1c773ea12009-04-28 19:58:421123 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521124 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521125
wezca1070932016-05-26 20:30:521126 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251127 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]d8fc4722014-06-13 13:17:151128 EXPECT_TRUE(response->proxy_server.IsEmpty());
initial.commit586acc5fe2008-07-26 22:42:521129
1130 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571131 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011132 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251133 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521134 }
1135}
1136
bncd16676a2016-07-20 16:23:011137TEST_F(HttpNetworkTransactionTest, Ignores100) {
danakj1fd259a02016-04-16 03:17:091138 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:221139 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:091140 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:221141 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:271142
[email protected]1c773ea12009-04-28 19:58:421143 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521144 request.method = "POST";
1145 request.url = GURL("http://www.foo.com/");
[email protected]329b68b2012-11-14 17:54:271146 request.upload_data_stream = &upload_data_stream;
initial.commit586acc5fe2008-07-26 22:42:521147 request.load_flags = 0;
1148
danakj1fd259a02016-04-16 03:17:091149 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1150 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411151 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271152
initial.commit586acc5fe2008-07-26 22:42:521153 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:351154 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1155 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1156 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061157 MockRead(SYNCHRONOUS, OK),
initial.commit586acc5fe2008-07-26 22:42:521158 };
[email protected]31a2bfe2010-02-09 08:03:391159 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071160 session_deps_.socket_factory->AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:521161
[email protected]49639fa2011-12-20 23:22:411162 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521163
[email protected]49639fa2011-12-20 23:22:411164 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011165 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521166
1167 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011168 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521169
[email protected]1c773ea12009-04-28 19:58:421170 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521171 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521172
wezca1070932016-05-26 20:30:521173 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251174 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521175
1176 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571177 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011178 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251179 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:521180}
1181
[email protected]3a2d3662009-03-27 03:49:141182// This test is almost the same as Ignores100 above, but the response contains
1183// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:571184// HTTP/1.1 and the two status headers are read in one read.
bncd16676a2016-07-20 16:23:011185TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:421186 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:141187 request.method = "GET";
1188 request.url = GURL("http://www.foo.com/");
1189 request.load_flags = 0;
1190
danakj1fd259a02016-04-16 03:17:091191 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1192 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411193 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271194
[email protected]3a2d3662009-03-27 03:49:141195 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:571196 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1197 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:141198 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061199 MockRead(SYNCHRONOUS, OK),
[email protected]3a2d3662009-03-27 03:49:141200 };
[email protected]31a2bfe2010-02-09 08:03:391201 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071202 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:141203
[email protected]49639fa2011-12-20 23:22:411204 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:141205
[email protected]49639fa2011-12-20 23:22:411206 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011207 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3a2d3662009-03-27 03:49:141208
1209 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011210 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141211
[email protected]1c773ea12009-04-28 19:58:421212 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521213 ASSERT_TRUE(response);
[email protected]3a2d3662009-03-27 03:49:141214
wezca1070932016-05-26 20:30:521215 EXPECT_TRUE(response->headers);
[email protected]3a2d3662009-03-27 03:49:141216 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1217
1218 std::string response_data;
1219 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011220 EXPECT_THAT(rv, IsOk());
[email protected]3a2d3662009-03-27 03:49:141221 EXPECT_EQ("hello world", response_data);
1222}
1223
bncd16676a2016-07-20 16:23:011224TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
zmo9528c9f42015-08-04 22:12:081225 HttpRequestInfo request;
1226 request.method = "POST";
1227 request.url = GURL("http://www.foo.com/");
1228 request.load_flags = 0;
1229
danakj1fd259a02016-04-16 03:17:091230 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1231 std::unique_ptr<HttpTransaction> trans(
zmo9528c9f42015-08-04 22:12:081232 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1233
1234 MockRead data_reads[] = {
1235 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1236 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381237 };
zmo9528c9f42015-08-04 22:12:081238 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1239 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381240
zmo9528c9f42015-08-04 22:12:081241 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381242
zmo9528c9f42015-08-04 22:12:081243 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011244 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381245
zmo9528c9f42015-08-04 22:12:081246 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011247 EXPECT_THAT(rv, IsOk());
[email protected]ee9410e72010-01-07 01:42:381248
zmo9528c9f42015-08-04 22:12:081249 std::string response_data;
1250 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011251 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:081252 EXPECT_EQ("", response_data);
[email protected]ee9410e72010-01-07 01:42:381253}
1254
bncd16676a2016-07-20 16:23:011255TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:381256 HttpRequestInfo request;
1257 request.method = "POST";
1258 request.url = GURL("http://www.foo.com/");
1259 request.load_flags = 0;
1260
danakj1fd259a02016-04-16 03:17:091261 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1262 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411263 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271264
[email protected]ee9410e72010-01-07 01:42:381265 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061266 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381267 };
[email protected]31a2bfe2010-02-09 08:03:391268 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071269 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]ee9410e72010-01-07 01:42:381270
[email protected]49639fa2011-12-20 23:22:411271 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381272
[email protected]49639fa2011-12-20 23:22:411273 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011274 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ee9410e72010-01-07 01:42:381275
1276 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011277 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]ee9410e72010-01-07 01:42:381278}
1279
[email protected]23e482282013-06-14 16:08:021280void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511281 const MockWrite* write_failure,
1282 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421283 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521284 request.method = "GET";
1285 request.url = GURL("http://www.foo.com/");
1286 request.load_flags = 0;
1287
vishal.b62985ca92015-04-17 08:45:511288 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071289 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091290 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271291
[email protected]202965992011-12-07 23:04:511292 // Written data for successfully sending both requests.
1293 MockWrite data1_writes[] = {
1294 MockWrite("GET / HTTP/1.1\r\n"
1295 "Host: www.foo.com\r\n"
1296 "Connection: keep-alive\r\n\r\n"),
1297 MockWrite("GET / HTTP/1.1\r\n"
1298 "Host: www.foo.com\r\n"
1299 "Connection: keep-alive\r\n\r\n")
1300 };
1301
1302 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521303 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351304 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1305 MockRead("hello"),
[email protected]8ddf8322012-02-23 18:08:061306 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521307 };
[email protected]202965992011-12-07 23:04:511308
1309 if (write_failure) {
[email protected]a34f61ee2014-03-18 20:59:491310 ASSERT_FALSE(read_failure);
[email protected]202965992011-12-07 23:04:511311 data1_writes[1] = *write_failure;
1312 } else {
1313 ASSERT_TRUE(read_failure);
1314 data1_reads[2] = *read_failure;
1315 }
1316
1317 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1318 data1_writes, arraysize(data1_writes));
[email protected]bb88e1d32013-05-03 23:11:071319 session_deps_.socket_factory->AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521320
1321 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351322 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1323 MockRead("world"),
[email protected]8ddf8322012-02-23 18:08:061324 MockRead(ASYNC, OK),
initial.commit586acc5fe2008-07-26 22:42:521325 };
[email protected]31a2bfe2010-02-09 08:03:391326 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071327 session_deps_.socket_factory->AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521328
thestig9d3bb0c2015-01-24 00:49:511329 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:521330 "hello", "world"
1331 };
1332
avibf0746c2015-12-09 19:53:141333 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
initial.commit586acc5fe2008-07-26 22:42:521334 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411335 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521336
danakj1fd259a02016-04-16 03:17:091337 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501338 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
initial.commit586acc5fe2008-07-26 22:42:521339
[email protected]49639fa2011-12-20 23:22:411340 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011341 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
initial.commit586acc5fe2008-07-26 22:42:521342
1343 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011344 EXPECT_THAT(rv, IsOk());
initial.commit586acc5fe2008-07-26 22:42:521345
[email protected]58e32bb2013-01-21 18:23:251346 LoadTimingInfo load_timing_info;
1347 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1348 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1349 if (i == 0) {
1350 first_socket_log_id = load_timing_info.socket_log_id;
1351 } else {
1352 // The second request should be using a new socket.
1353 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1354 }
1355
[email protected]1c773ea12009-04-28 19:58:421356 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521357 ASSERT_TRUE(response);
initial.commit586acc5fe2008-07-26 22:42:521358
wezca1070932016-05-26 20:30:521359 EXPECT_TRUE(response->headers);
[email protected]3d2a59b2008-09-26 19:44:251360 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521361
1362 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571363 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011364 EXPECT_THAT(rv, IsOk());
[email protected]3d2a59b2008-09-26 19:44:251365 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521366 }
1367}
[email protected]3d2a59b2008-09-26 19:44:251368
[email protected]a34f61ee2014-03-18 20:59:491369void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1370 const MockWrite* write_failure,
[email protected]09356c652014-03-25 15:36:101371 const MockRead* read_failure,
1372 bool use_spdy) {
[email protected]a34f61ee2014-03-18 20:59:491373 HttpRequestInfo request;
1374 request.method = "GET";
[email protected]09356c652014-03-25 15:36:101375 request.url = GURL("https://www.foo.com/");
[email protected]a34f61ee2014-03-18 20:59:491376 request.load_flags = 0;
1377
vishal.b62985ca92015-04-17 08:45:511378 TestNetLog net_log;
[email protected]a34f61ee2014-03-18 20:59:491379 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091380 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a34f61ee2014-03-18 20:59:491381
[email protected]09356c652014-03-25 15:36:101382 SSLSocketDataProvider ssl1(ASYNC, OK);
1383 SSLSocketDataProvider ssl2(ASYNC, OK);
1384 if (use_spdy) {
bnc3cf2a592016-08-11 14:48:361385 ssl1.next_proto = kProtoHTTP2;
1386 ssl2.next_proto = kProtoHTTP2;
[email protected]09356c652014-03-25 15:36:101387 }
1388 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1389 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]a34f61ee2014-03-18 20:59:491390
[email protected]09356c652014-03-25 15:36:101391 // SPDY versions of the request and response.
bncdf80d44fd2016-07-15 20:27:411392 SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
bnc38dcd392016-02-09 23:19:491393 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
bncdf80d44fd2016-07-15 20:27:411394 SpdySerializedFrame spdy_response(
bnc42331402016-07-25 13:36:151395 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:411396 SpdySerializedFrame spdy_data(
1397 spdy_util_.ConstructSpdyDataFrame(1, "hello", 5, true));
[email protected]a34f61ee2014-03-18 20:59:491398
[email protected]09356c652014-03-25 15:36:101399 // HTTP/1.1 versions of the request and response.
1400 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1401 "Host: www.foo.com\r\n"
1402 "Connection: keep-alive\r\n\r\n";
1403 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1404 const char kHttpData[] = "hello";
1405
1406 std::vector<MockRead> data1_reads;
1407 std::vector<MockWrite> data1_writes;
[email protected]a34f61ee2014-03-18 20:59:491408 if (write_failure) {
1409 ASSERT_FALSE(read_failure);
[email protected]09356c652014-03-25 15:36:101410 data1_writes.push_back(*write_failure);
1411 data1_reads.push_back(MockRead(ASYNC, OK));
[email protected]a34f61ee2014-03-18 20:59:491412 } else {
1413 ASSERT_TRUE(read_failure);
[email protected]09356c652014-03-25 15:36:101414 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411415 data1_writes.push_back(CreateMockWrite(spdy_request));
[email protected]09356c652014-03-25 15:36:101416 } else {
1417 data1_writes.push_back(MockWrite(kHttpRequest));
1418 }
1419 data1_reads.push_back(*read_failure);
[email protected]a34f61ee2014-03-18 20:59:491420 }
1421
[email protected]09356c652014-03-25 15:36:101422 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1423 &data1_writes[0], data1_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491424 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1425
[email protected]09356c652014-03-25 15:36:101426 std::vector<MockRead> data2_reads;
1427 std::vector<MockWrite> data2_writes;
1428
1429 if (use_spdy) {
bncdf80d44fd2016-07-15 20:27:411430 data2_writes.push_back(CreateMockWrite(spdy_request, 0, ASYNC));
[email protected]09356c652014-03-25 15:36:101431
bncdf80d44fd2016-07-15 20:27:411432 data2_reads.push_back(CreateMockRead(spdy_response, 1, ASYNC));
1433 data2_reads.push_back(CreateMockRead(spdy_data, 2, ASYNC));
[email protected]09356c652014-03-25 15:36:101434 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1435 } else {
1436 data2_writes.push_back(
1437 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1438
1439 data2_reads.push_back(
1440 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1441 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1442 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1443 }
rch8e6c6c42015-05-01 14:05:131444 SequencedSocketData data2(&data2_reads[0], data2_reads.size(),
1445 &data2_writes[0], data2_writes.size());
[email protected]a34f61ee2014-03-18 20:59:491446 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1447
1448 // Preconnect a socket.
nharper8cdb0fb2016-04-22 21:34:591449 session->http_stream_factory()->PreconnectStreams(1, request);
[email protected]a34f61ee2014-03-18 20:59:491450 // Wait for the preconnect to complete.
1451 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1452 base::RunLoop().RunUntilIdle();
[email protected]09356c652014-03-25 15:36:101453 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]a34f61ee2014-03-18 20:59:491454
1455 // Make the request.
1456 TestCompletionCallback callback;
1457
danakj1fd259a02016-04-16 03:17:091458 std::unique_ptr<HttpTransaction> trans(
[email protected]a34f61ee2014-03-18 20:59:491459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1460
1461 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011462 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a34f61ee2014-03-18 20:59:491463
1464 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011465 EXPECT_THAT(rv, IsOk());
[email protected]a34f61ee2014-03-18 20:59:491466
1467 LoadTimingInfo load_timing_info;
1468 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
[email protected]09356c652014-03-25 15:36:101469 TestLoadTimingNotReused(
1470 load_timing_info,
1471 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]a34f61ee2014-03-18 20:59:491472
1473 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:521474 ASSERT_TRUE(response);
[email protected]a34f61ee2014-03-18 20:59:491475
wezca1070932016-05-26 20:30:521476 EXPECT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:021477 if (response->was_fetched_via_spdy) {
1478 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
1479 } else {
1480 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1481 }
[email protected]a34f61ee2014-03-18 20:59:491482
1483 std::string response_data;
1484 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011485 EXPECT_THAT(rv, IsOk());
[email protected]09356c652014-03-25 15:36:101486 EXPECT_EQ(kHttpData, response_data);
[email protected]a34f61ee2014-03-18 20:59:491487}
1488
bncd16676a2016-07-20 16:23:011489TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
[email protected]8ddf8322012-02-23 18:08:061490 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511491 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1492}
1493
bncd16676a2016-07-20 16:23:011494TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061495 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511496 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251497}
1498
bncd16676a2016-07-20 16:23:011499TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]8ddf8322012-02-23 18:08:061500 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]202965992011-12-07 23:04:511501 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251502}
1503
[email protected]d58ceea82014-06-04 10:55:541504// Make sure that on a 408 response (Request Timeout), the request is retried,
1505// if the socket was a reused keep alive socket.
bncd16676a2016-07-20 16:23:011506TEST_F(HttpNetworkTransactionTest, KeepAlive408) {
[email protected]d58ceea82014-06-04 10:55:541507 MockRead read_failure(SYNCHRONOUS,
1508 "HTTP/1.1 408 Request Timeout\r\n"
1509 "Connection: Keep-Alive\r\n"
1510 "Content-Length: 6\r\n\r\n"
1511 "Pickle");
1512 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1513}
1514
bncd16676a2016-07-20 16:23:011515TEST_F(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
[email protected]a34f61ee2014-03-18 20:59:491516 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]09356c652014-03-25 15:36:101517 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
[email protected]a34f61ee2014-03-18 20:59:491518}
1519
bncd16676a2016-07-20 16:23:011520TEST_F(HttpNetworkTransactionTest, PreconnectErrorReset) {
[email protected]a34f61ee2014-03-18 20:59:491521 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
[email protected]09356c652014-03-25 15:36:101522 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
[email protected]a34f61ee2014-03-18 20:59:491523}
1524
bncd16676a2016-07-20 16:23:011525TEST_F(HttpNetworkTransactionTest, PreconnectErrorEOF) {
[email protected]a34f61ee2014-03-18 20:59:491526 MockRead read_failure(SYNCHRONOUS, OK); // EOF
[email protected]09356c652014-03-25 15:36:101527 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1528}
1529
bncd16676a2016-07-20 16:23:011530TEST_F(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101531 MockRead read_failure(ASYNC, OK); // EOF
1532 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1533}
1534
[email protected]d58ceea82014-06-04 10:55:541535// Make sure that on a 408 response (Request Timeout), the request is retried,
1536// if the socket was a preconnected (UNUSED_IDLE) socket.
bncd16676a2016-07-20 16:23:011537TEST_F(HttpNetworkTransactionTest, RetryOnIdle408) {
[email protected]d58ceea82014-06-04 10:55:541538 MockRead read_failure(SYNCHRONOUS,
1539 "HTTP/1.1 408 Request Timeout\r\n"
1540 "Connection: Keep-Alive\r\n"
1541 "Content-Length: 6\r\n\r\n"
1542 "Pickle");
1543 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1544 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1545}
1546
bncd16676a2016-07-20 16:23:011547TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
[email protected]09356c652014-03-25 15:36:101548 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1549 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1550}
1551
bncd16676a2016-07-20 16:23:011552TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
[email protected]09356c652014-03-25 15:36:101553 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1554 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1555}
1556
bncd16676a2016-07-20 16:23:011557TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
[email protected]09356c652014-03-25 15:36:101558 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1559 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1560}
1561
bncd16676a2016-07-20 16:23:011562TEST_F(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
[email protected]09356c652014-03-25 15:36:101563 MockRead read_failure(ASYNC, OK); // EOF
1564 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
[email protected]a34f61ee2014-03-18 20:59:491565}
1566
bncd16676a2016-07-20 16:23:011567TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421568 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251569 request.method = "GET";
bncce36dca22015-04-21 22:11:231570 request.url = GURL("http://www.example.org/");
[email protected]3d2a59b2008-09-26 19:44:251571 request.load_flags = 0;
1572
danakj1fd259a02016-04-16 03:17:091573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1574 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:411575 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:271576
[email protected]3d2a59b2008-09-26 19:44:251577 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061578 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351579 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1580 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061581 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251582 };
[email protected]31a2bfe2010-02-09 08:03:391583 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071584 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251585
[email protected]49639fa2011-12-20 23:22:411586 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251587
[email protected]49639fa2011-12-20 23:22:411588 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011589 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3d2a59b2008-09-26 19:44:251590
1591 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011592 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:591593
1594 IPEndPoint endpoint;
1595 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
1596 EXPECT_LT(0u, endpoint.address().size());
[email protected]3d2a59b2008-09-26 19:44:251597}
1598
1599// What do various browsers do when the server closes a non-keepalive
1600// connection without sending any response header or body?
1601//
1602// IE7: error page
1603// Safari 3.1.2 (Windows): error page
1604// Firefox 3.0.1: blank page
1605// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421606// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1607// Us: error page (EMPTY_RESPONSE)
bncd16676a2016-07-20 16:23:011608TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
[email protected]3d2a59b2008-09-26 19:44:251609 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:061610 MockRead(SYNCHRONOUS, OK), // EOF
[email protected]217e6022008-09-29 18:18:351611 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1612 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:061613 MockRead(SYNCHRONOUS, OK),
[email protected]3d2a59b2008-09-26 19:44:251614 };
[email protected]31a2bfe2010-02-09 08:03:391615 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1616 arraysize(data_reads));
robpercival214763f2016-07-01 23:27:011617 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
[email protected]3d2a59b2008-09-26 19:44:251618}
[email protected]1826a402014-01-08 15:40:481619
[email protected]7a5378b2012-11-04 03:25:171620// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1621// tests. There was a bug causing HttpNetworkTransaction to hang in the
1622// destructor in such situations.
1623// See http://crbug.com/154712 and http://crbug.com/156609.
bncd16676a2016-07-20 16:23:011624TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
[email protected]7a5378b2012-11-04 03:25:171625 HttpRequestInfo request;
1626 request.method = "GET";
bncce36dca22015-04-21 22:11:231627 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171628 request.load_flags = 0;
1629
danakj1fd259a02016-04-16 03:17:091630 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1631 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501632 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171633
1634 MockRead data_reads[] = {
1635 MockRead("HTTP/1.0 200 OK\r\n"),
1636 MockRead("Connection: keep-alive\r\n"),
1637 MockRead("Content-Length: 100\r\n\r\n"),
1638 MockRead("hello"),
1639 MockRead(SYNCHRONOUS, 0),
1640 };
1641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071642 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171643
1644 TestCompletionCallback callback;
1645
1646 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011647 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:171648
1649 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011650 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:171651
1652 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501653 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171654 if (rv == ERR_IO_PENDING)
1655 rv = callback.WaitForResult();
1656 EXPECT_EQ(5, rv);
[email protected]90499482013-06-01 00:39:501657 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
robpercival214763f2016-07-01 23:27:011658 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:171659
1660 trans.reset();
fdoray92e35a72016-06-10 15:54:551661 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171662 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1663}
1664
bncd16676a2016-07-20 16:23:011665TEST_F(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
[email protected]7a5378b2012-11-04 03:25:171666 HttpRequestInfo request;
1667 request.method = "GET";
bncce36dca22015-04-21 22:11:231668 request.url = GURL("http://www.example.org/");
[email protected]7a5378b2012-11-04 03:25:171669 request.load_flags = 0;
1670
danakj1fd259a02016-04-16 03:17:091671 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1672 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501673 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a5378b2012-11-04 03:25:171674
1675 MockRead data_reads[] = {
1676 MockRead("HTTP/1.0 200 OK\r\n"),
1677 MockRead("Connection: keep-alive\r\n"),
1678 MockRead("Content-Length: 100\r\n\r\n"),
1679 MockRead(SYNCHRONOUS, 0),
1680 };
1681 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:071682 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]7a5378b2012-11-04 03:25:171683
1684 TestCompletionCallback callback;
1685
1686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011687 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a5378b2012-11-04 03:25:171688
1689 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011690 EXPECT_THAT(rv, IsOk());
[email protected]7a5378b2012-11-04 03:25:171691
1692 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
[email protected]90499482013-06-01 00:39:501693 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7a5378b2012-11-04 03:25:171694 if (rv == ERR_IO_PENDING)
1695 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:011696 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]7a5378b2012-11-04 03:25:171697
1698 trans.reset();
fdoray92e35a72016-06-10 15:54:551699 base::RunLoop().RunUntilIdle();
[email protected]7a5378b2012-11-04 03:25:171700 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1701}
1702
[email protected]0b0bf032010-09-21 18:08:501703// Test that we correctly reuse a keep-alive connection after not explicitly
1704// reading the body.
bncd16676a2016-07-20 16:23:011705TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131706 HttpRequestInfo request;
1707 request.method = "GET";
1708 request.url = GURL("http://www.foo.com/");
1709 request.load_flags = 0;
1710
vishal.b62985ca92015-04-17 08:45:511711 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:071712 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:091713 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:271714
mmenkecc2298e2015-12-07 18:20:181715 const char* request_data =
1716 "GET / HTTP/1.1\r\n"
1717 "Host: www.foo.com\r\n"
1718 "Connection: keep-alive\r\n\r\n";
1719 MockWrite data_writes[] = {
1720 MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data),
1721 MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data),
1722 MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data),
1723 MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data),
1724 MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data),
1725 };
1726
[email protected]0b0bf032010-09-21 18:08:501727 // Note that because all these reads happen in the same
1728 // StaticSocketDataProvider, it shows that the same socket is being reused for
1729 // all transactions.
mmenkecc2298e2015-12-07 18:20:181730 MockRead data_reads[] = {
1731 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
1732 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
1733 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
1734 MockRead(ASYNC, 7,
1735 "HTTP/1.1 302 Found\r\n"
1736 "Content-Length: 0\r\n\r\n"),
1737 MockRead(ASYNC, 9,
1738 "HTTP/1.1 302 Found\r\n"
1739 "Content-Length: 5\r\n\r\n"
1740 "hello"),
1741 MockRead(ASYNC, 11,
1742 "HTTP/1.1 301 Moved Permanently\r\n"
1743 "Content-Length: 0\r\n\r\n"),
1744 MockRead(ASYNC, 13,
1745 "HTTP/1.1 301 Moved Permanently\r\n"
1746 "Content-Length: 5\r\n\r\n"
1747 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131748
mmenkecc2298e2015-12-07 18:20:181749 // In the next two rounds, IsConnectedAndIdle returns false, due to
1750 // the set_busy_before_sync_reads(true) call, while the
1751 // HttpNetworkTransaction is being shut down, but the socket is still
1752 // reuseable. See http://crbug.com/544255.
1753 MockRead(ASYNC, 15,
1754 "HTTP/1.1 200 Hunky-Dory\r\n"
1755 "Content-Length: 5\r\n\r\n"),
1756 MockRead(SYNCHRONOUS, 16, "hello"),
[email protected]fc31d6a42010-06-24 18:05:131757
mmenkecc2298e2015-12-07 18:20:181758 MockRead(ASYNC, 18,
1759 "HTTP/1.1 200 Hunky-Dory\r\n"
1760 "Content-Length: 5\r\n\r\n"
1761 "he"),
1762 MockRead(SYNCHRONOUS, 19, "llo"),
1763
1764 // The body of the final request is actually read.
1765 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1766 MockRead(ASYNC, 22, "hello"),
1767 };
1768 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
1769 arraysize(data_writes));
1770 data.set_busy_before_sync_reads(true);
1771 session_deps_.socket_factory->AddSocketDataProvider(&data);
1772
1773 const int kNumUnreadBodies = arraysize(data_writes) - 1;
[email protected]0b0bf032010-09-21 18:08:501774 std::string response_lines[kNumUnreadBodies];
1775
avibf0746c2015-12-09 19:53:141776 uint32_t first_socket_log_id = NetLog::Source::kInvalidId;
mmenkecc2298e2015-12-07 18:20:181777 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
[email protected]49639fa2011-12-20 23:22:411778 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131779
danakj1fd259a02016-04-16 03:17:091780 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501781 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]fc31d6a42010-06-24 18:05:131782
[email protected]49639fa2011-12-20 23:22:411783 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011784 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]fc31d6a42010-06-24 18:05:131785
[email protected]58e32bb2013-01-21 18:23:251786 LoadTimingInfo load_timing_info;
1787 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1788 if (i == 0) {
1789 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1790 first_socket_log_id = load_timing_info.socket_log_id;
1791 } else {
1792 TestLoadTimingReused(load_timing_info);
1793 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1794 }
1795
[email protected]fc31d6a42010-06-24 18:05:131796 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181797 ASSERT_TRUE(response);
[email protected]fc31d6a42010-06-24 18:05:131798
mmenkecc2298e2015-12-07 18:20:181799 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501800 response_lines[i] = response->headers->GetStatusLine();
1801
mmenkecc2298e2015-12-07 18:20:181802 // Delete the transaction without reading the response bodies. Then spin
1803 // the message loop, so the response bodies are drained.
1804 trans.reset();
1805 base::RunLoop().RunUntilIdle();
[email protected]fc31d6a42010-06-24 18:05:131806 }
[email protected]0b0bf032010-09-21 18:08:501807
1808 const char* const kStatusLines[] = {
mmenkecc2298e2015-12-07 18:20:181809 "HTTP/1.1 204 No Content",
1810 "HTTP/1.1 205 Reset Content",
1811 "HTTP/1.1 304 Not Modified",
1812 "HTTP/1.1 302 Found",
1813 "HTTP/1.1 302 Found",
1814 "HTTP/1.1 301 Moved Permanently",
1815 "HTTP/1.1 301 Moved Permanently",
1816 "HTTP/1.1 200 Hunky-Dory",
1817 "HTTP/1.1 200 Hunky-Dory",
[email protected]0b0bf032010-09-21 18:08:501818 };
1819
mostynb91e0da982015-01-20 19:17:271820 static_assert(kNumUnreadBodies == arraysize(kStatusLines),
1821 "forgot to update kStatusLines");
[email protected]0b0bf032010-09-21 18:08:501822
1823 for (int i = 0; i < kNumUnreadBodies; ++i)
1824 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1825
[email protected]49639fa2011-12-20 23:22:411826 TestCompletionCallback callback;
danakj1fd259a02016-04-16 03:17:091827 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:501828 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:411829 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011830 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]0b0bf032010-09-21 18:08:501831 const HttpResponseInfo* response = trans->GetResponseInfo();
mmenkecc2298e2015-12-07 18:20:181832 ASSERT_TRUE(response);
1833 ASSERT_TRUE(response->headers);
[email protected]0b0bf032010-09-21 18:08:501834 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1835 std::string response_data;
1836 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:011837 EXPECT_THAT(rv, IsOk());
[email protected]0b0bf032010-09-21 18:08:501838 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131839}
1840
mmenke5f94fda2016-06-02 20:54:131841// Sockets that receive extra data after a response is complete should not be
1842// reused.
bncd16676a2016-07-20 16:23:011843TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
mmenke5f94fda2016-06-02 20:54:131844 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1845 MockWrite data_writes1[] = {
1846 MockWrite("HEAD / HTTP/1.1\r\n"
1847 "Host: www.borked.com\r\n"
1848 "Connection: keep-alive\r\n\r\n"),
1849 };
1850
1851 MockRead data_reads1[] = {
1852 MockRead("HTTP/1.1 200 OK\r\n"
1853 "Connection: keep-alive\r\n"
1854 "Content-Length: 22\r\n\r\n"
1855 "This server is borked."),
1856 };
1857
1858 MockWrite data_writes2[] = {
1859 MockWrite("GET /foo HTTP/1.1\r\n"
1860 "Host: www.borked.com\r\n"
1861 "Connection: keep-alive\r\n\r\n"),
1862 };
1863
1864 MockRead data_reads2[] = {
1865 MockRead("HTTP/1.1 200 OK\r\n"
1866 "Content-Length: 3\r\n\r\n"
1867 "foo"),
1868 };
1869 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1870 data_writes1, arraysize(data_writes1));
1871 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1872 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1873 data_writes2, arraysize(data_writes2));
1874 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1875
1876 TestCompletionCallback callback;
1877 HttpRequestInfo request1;
1878 request1.method = "HEAD";
1879 request1.url = GURL("http://www.borked.com/");
1880
1881 std::unique_ptr<HttpTransaction> trans1(
1882 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1883 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011884 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:131885
1886 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1887 ASSERT_TRUE(response1);
1888 ASSERT_TRUE(response1->headers);
1889 EXPECT_EQ(200, response1->headers->response_code());
1890 EXPECT_TRUE(response1->headers->IsKeepAlive());
1891
1892 std::string response_data1;
robpercival214763f2016-07-01 23:27:011893 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:131894 EXPECT_EQ("", response_data1);
1895 // Deleting the transaction attempts to release the socket back into the
1896 // socket pool.
1897 trans1.reset();
1898
1899 HttpRequestInfo request2;
1900 request2.method = "GET";
1901 request2.url = GURL("http://www.borked.com/foo");
1902
1903 std::unique_ptr<HttpTransaction> trans2(
1904 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1905 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011906 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:131907
1908 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1909 ASSERT_TRUE(response2);
1910 ASSERT_TRUE(response2->headers);
1911 EXPECT_EQ(200, response2->headers->response_code());
1912
1913 std::string response_data2;
robpercival214763f2016-07-01 23:27:011914 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:131915 EXPECT_EQ("foo", response_data2);
1916}
1917
bncd16676a2016-07-20 16:23:011918TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
mmenke5f94fda2016-06-02 20:54:131919 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1920 MockWrite data_writes1[] = {
1921 MockWrite("GET / HTTP/1.1\r\n"
1922 "Host: www.borked.com\r\n"
1923 "Connection: keep-alive\r\n\r\n"),
1924 };
1925
1926 MockRead data_reads1[] = {
1927 MockRead("HTTP/1.1 200 OK\r\n"
1928 "Connection: keep-alive\r\n"
1929 "Content-Length: 22\r\n\r\n"
1930 "This server is borked."
1931 "Bonus data!"),
1932 };
1933
1934 MockWrite data_writes2[] = {
1935 MockWrite("GET /foo HTTP/1.1\r\n"
1936 "Host: www.borked.com\r\n"
1937 "Connection: keep-alive\r\n\r\n"),
1938 };
1939
1940 MockRead data_reads2[] = {
1941 MockRead("HTTP/1.1 200 OK\r\n"
1942 "Content-Length: 3\r\n\r\n"
1943 "foo"),
1944 };
1945 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1946 data_writes1, arraysize(data_writes1));
1947 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1948 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1949 data_writes2, arraysize(data_writes2));
1950 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1951
1952 TestCompletionCallback callback;
1953 HttpRequestInfo request1;
1954 request1.method = "GET";
1955 request1.url = GURL("http://www.borked.com/");
1956
1957 std::unique_ptr<HttpTransaction> trans1(
1958 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1959 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011960 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:131961
1962 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1963 ASSERT_TRUE(response1);
1964 ASSERT_TRUE(response1->headers);
1965 EXPECT_EQ(200, response1->headers->response_code());
1966 EXPECT_TRUE(response1->headers->IsKeepAlive());
1967
1968 std::string response_data1;
robpercival214763f2016-07-01 23:27:011969 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:131970 EXPECT_EQ("This server is borked.", response_data1);
1971 // Deleting the transaction attempts to release the socket back into the
1972 // socket pool.
1973 trans1.reset();
1974
1975 HttpRequestInfo request2;
1976 request2.method = "GET";
1977 request2.url = GURL("http://www.borked.com/foo");
1978
1979 std::unique_ptr<HttpTransaction> trans2(
1980 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1981 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:011982 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:131983
1984 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1985 ASSERT_TRUE(response2);
1986 ASSERT_TRUE(response2->headers);
1987 EXPECT_EQ(200, response2->headers->response_code());
1988
1989 std::string response_data2;
robpercival214763f2016-07-01 23:27:011990 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:131991 EXPECT_EQ("foo", response_data2);
1992}
1993
bncd16676a2016-07-20 16:23:011994TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
mmenke5f94fda2016-06-02 20:54:131995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1996 MockWrite data_writes1[] = {
1997 MockWrite("GET / HTTP/1.1\r\n"
1998 "Host: www.borked.com\r\n"
1999 "Connection: keep-alive\r\n\r\n"),
2000 };
2001
2002 MockRead data_reads1[] = {
2003 MockRead("HTTP/1.1 200 OK\r\n"
2004 "Connection: keep-alive\r\n"
2005 "Transfer-Encoding: chunked\r\n\r\n"),
2006 MockRead("16\r\nThis server is borked.\r\n"),
2007 MockRead("0\r\n\r\nBonus data!"),
2008 };
2009
2010 MockWrite data_writes2[] = {
2011 MockWrite("GET /foo HTTP/1.1\r\n"
2012 "Host: www.borked.com\r\n"
2013 "Connection: keep-alive\r\n\r\n"),
2014 };
2015
2016 MockRead data_reads2[] = {
2017 MockRead("HTTP/1.1 200 OK\r\n"
2018 "Content-Length: 3\r\n\r\n"
2019 "foo"),
2020 };
2021 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2022 data_writes1, arraysize(data_writes1));
2023 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2024 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2025 data_writes2, arraysize(data_writes2));
2026 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2027
2028 TestCompletionCallback callback;
2029 HttpRequestInfo request1;
2030 request1.method = "GET";
2031 request1.url = GURL("http://www.borked.com/");
2032
2033 std::unique_ptr<HttpTransaction> trans1(
2034 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2035 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012036 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132037
2038 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2039 ASSERT_TRUE(response1);
2040 ASSERT_TRUE(response1->headers);
2041 EXPECT_EQ(200, response1->headers->response_code());
2042 EXPECT_TRUE(response1->headers->IsKeepAlive());
2043
2044 std::string response_data1;
robpercival214763f2016-07-01 23:27:012045 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
mmenke5f94fda2016-06-02 20:54:132046 EXPECT_EQ("This server is borked.", response_data1);
2047 // Deleting the transaction attempts to release the socket back into the
2048 // socket pool.
2049 trans1.reset();
2050
2051 HttpRequestInfo request2;
2052 request2.method = "GET";
2053 request2.url = GURL("http://www.borked.com/foo");
2054
2055 std::unique_ptr<HttpTransaction> trans2(
2056 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2057 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012058 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132059
2060 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2061 ASSERT_TRUE(response2);
2062 ASSERT_TRUE(response2->headers);
2063 EXPECT_EQ(200, response2->headers->response_code());
2064
2065 std::string response_data2;
robpercival214763f2016-07-01 23:27:012066 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
mmenke5f94fda2016-06-02 20:54:132067 EXPECT_EQ("foo", response_data2);
2068}
2069
2070// This is a little different from the others - it tests the case that the
2071// HttpStreamParser doesn't know if there's extra data on a socket or not when
2072// the HttpNetworkTransaction is torn down, because the response body hasn't
2073// been read from yet, but the request goes through the HttpResponseBodyDrainer.
bncd16676a2016-07-20 16:23:012074TEST_F(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
mmenke5f94fda2016-06-02 20:54:132075 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2076 MockWrite data_writes1[] = {
2077 MockWrite("GET / HTTP/1.1\r\n"
2078 "Host: www.borked.com\r\n"
2079 "Connection: keep-alive\r\n\r\n"),
2080 };
2081
2082 MockRead data_reads1[] = {
2083 MockRead("HTTP/1.1 200 OK\r\n"
2084 "Connection: keep-alive\r\n"
2085 "Transfer-Encoding: chunked\r\n\r\n"),
2086 MockRead("16\r\nThis server is borked.\r\n"),
2087 MockRead("0\r\n\r\nBonus data!"),
2088 };
2089 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2090 data_writes1, arraysize(data_writes1));
2091 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2092
2093 TestCompletionCallback callback;
2094 HttpRequestInfo request1;
2095 request1.method = "GET";
2096 request1.url = GURL("http://www.borked.com/");
2097
2098 std::unique_ptr<HttpTransaction> trans1(
2099 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2100 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012101 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke5f94fda2016-06-02 20:54:132102
2103 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2104 ASSERT_TRUE(response1);
2105 ASSERT_TRUE(response1->headers);
2106 EXPECT_EQ(200, response1->headers->response_code());
2107 EXPECT_TRUE(response1->headers->IsKeepAlive());
2108
2109 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2110 // response body.
2111 trans1.reset();
2112
2113 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2114 // socket can't be reused, rather than returning it to the socket pool.
2115 base::RunLoop().RunUntilIdle();
2116
2117 // There should be no idle sockets in the pool.
2118 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2119}
2120
[email protected]038e9a32008-10-08 22:40:162121// Test the request-challenge-retry sequence for basic auth.
2122// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012123TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:422124 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162125 request.method = "GET";
bncce36dca22015-04-21 22:11:232126 request.url = GURL("http://www.example.org/");
[email protected]038e9a32008-10-08 22:40:162127 request.load_flags = 0;
2128
vishal.b62985ca92015-04-17 08:45:512129 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072130 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092131 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2132 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412133 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272134
[email protected]f9ee6b52008-11-08 06:46:232135 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232136 MockWrite(
2137 "GET / HTTP/1.1\r\n"
2138 "Host: www.example.org\r\n"
2139 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232140 };
2141
[email protected]038e9a32008-10-08 22:40:162142 MockRead data_reads1[] = {
2143 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2144 // Give a couple authenticate options (only the middle one is actually
2145 // supported).
[email protected]22927ad2009-09-21 19:56:192146 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162147 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2148 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2149 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2150 // Large content-length -- won't matter, as connection will be reset.
2151 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062152 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162153 };
2154
2155 // After calling trans->RestartWithAuth(), this is the request we should
2156 // be issuing -- the final header line contains the credentials.
2157 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232158 MockWrite(
2159 "GET / HTTP/1.1\r\n"
2160 "Host: www.example.org\r\n"
2161 "Connection: keep-alive\r\n"
2162 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:162163 };
2164
2165 // Lastly, the server responds with the actual content.
2166 MockRead data_reads2[] = {
2167 MockRead("HTTP/1.0 200 OK\r\n"),
2168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2169 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062170 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162171 };
2172
[email protected]31a2bfe2010-02-09 08:03:392173 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2174 data_writes1, arraysize(data_writes1));
2175 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2176 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072177 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2178 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:162179
[email protected]49639fa2011-12-20 23:22:412180 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162181
[email protected]49639fa2011-12-20 23:22:412182 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012183 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162184
2185 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012186 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162187
[email protected]58e32bb2013-01-21 18:23:252188 LoadTimingInfo load_timing_info1;
2189 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2190 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2191
sclittlefb249892015-09-10 21:33:222192 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2193 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2194 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
[email protected]b8015c42013-12-24 15:18:192195 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2196
[email protected]1c773ea12009-04-28 19:58:422197 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522198 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:042199 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162200
[email protected]49639fa2011-12-20 23:22:412201 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162202
[email protected]49639fa2011-12-20 23:22:412203 rv = trans->RestartWithAuth(
2204 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012205 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:162206
2207 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012208 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:162209
[email protected]58e32bb2013-01-21 18:23:252210 LoadTimingInfo load_timing_info2;
2211 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2212 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2213 // The load timing after restart should have a new socket ID, and times after
2214 // those of the first load timing.
2215 EXPECT_LE(load_timing_info1.receive_headers_end,
2216 load_timing_info2.connect_timing.connect_start);
2217 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2218
sclittlefb249892015-09-10 21:33:222219 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2220 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2221 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
[email protected]b8015c42013-12-24 15:18:192222 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2223
[email protected]038e9a32008-10-08 22:40:162224 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522225 ASSERT_TRUE(response);
2226 EXPECT_FALSE(response->auth_challenge);
[email protected]038e9a32008-10-08 22:40:162227 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162228}
2229
ttuttled9dbc652015-09-29 20:00:592230// Test the request-challenge-retry sequence for basic auth.
2231// (basic auth is the easiest to mock, because it has no randomness).
bncd16676a2016-07-20 16:23:012232TEST_F(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
ttuttled9dbc652015-09-29 20:00:592233 HttpRequestInfo request;
2234 request.method = "GET";
2235 request.url = GURL("http://www.example.org/");
2236 request.load_flags = 0;
2237
2238 TestNetLog log;
2239 MockHostResolver* resolver = new MockHostResolver();
2240 session_deps_.net_log = &log;
2241 session_deps_.host_resolver.reset(resolver);
danakj1fd259a02016-04-16 03:17:092242 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
2243 std::unique_ptr<HttpTransaction> trans(
ttuttled9dbc652015-09-29 20:00:592244 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2245
2246 resolver->rules()->ClearRules();
2247 resolver->rules()->AddRule("www.example.org", "127.0.0.1");
2248
2249 MockWrite data_writes1[] = {
2250 MockWrite("GET / HTTP/1.1\r\n"
2251 "Host: www.example.org\r\n"
2252 "Connection: keep-alive\r\n\r\n"),
2253 };
2254
2255 MockRead data_reads1[] = {
2256 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2257 // Give a couple authenticate options (only the middle one is actually
2258 // supported).
2259 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2260 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2261 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2262 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2263 // Large content-length -- won't matter, as connection will be reset.
2264 MockRead("Content-Length: 10000\r\n\r\n"),
2265 MockRead(SYNCHRONOUS, ERR_FAILED),
2266 };
2267
2268 // After calling trans->RestartWithAuth(), this is the request we should
2269 // be issuing -- the final header line contains the credentials.
2270 MockWrite data_writes2[] = {
2271 MockWrite("GET / HTTP/1.1\r\n"
2272 "Host: www.example.org\r\n"
2273 "Connection: keep-alive\r\n"
2274 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2275 };
2276
2277 // Lastly, the server responds with the actual content.
2278 MockRead data_reads2[] = {
2279 MockRead("HTTP/1.0 200 OK\r\n"),
2280 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2281 MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
2282 };
2283
2284 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2285 data_writes1, arraysize(data_writes1));
2286 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2287 data_writes2, arraysize(data_writes2));
2288 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2289 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2290
2291 TestCompletionCallback callback1;
2292
2293 EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
2294 BoundNetLog())));
2295
2296 LoadTimingInfo load_timing_info1;
2297 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2298 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2299
2300 int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
2301 EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
2302 int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
2303 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2304
2305 const HttpResponseInfo* response = trans->GetResponseInfo();
2306 ASSERT_TRUE(response);
2307 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2308
2309 IPEndPoint endpoint;
2310 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2311 ASSERT_FALSE(endpoint.address().empty());
2312 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
2313
2314 resolver->rules()->ClearRules();
2315 resolver->rules()->AddRule("www.example.org", "127.0.0.2");
2316
2317 TestCompletionCallback callback2;
2318
2319 EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
2320 AuthCredentials(kFoo, kBar), callback2.callback())));
2321
2322 LoadTimingInfo load_timing_info2;
2323 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2324 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
2325 // The load timing after restart should have a new socket ID, and times after
2326 // those of the first load timing.
2327 EXPECT_LE(load_timing_info1.receive_headers_end,
2328 load_timing_info2.connect_timing.connect_start);
2329 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2330
2331 int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
2332 EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
2333 int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
2334 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
2335
2336 response = trans->GetResponseInfo();
2337 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:522338 EXPECT_FALSE(response->auth_challenge);
ttuttled9dbc652015-09-29 20:00:592339 EXPECT_EQ(100, response->headers->GetContentLength());
2340
2341 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
2342 ASSERT_FALSE(endpoint.address().empty());
2343 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
2344}
2345
bncd16676a2016-07-20 16:23:012346TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:462347 HttpRequestInfo request;
2348 request.method = "GET";
bncce36dca22015-04-21 22:11:232349 request.url = GURL("http://www.example.org/");
ttuttle859dc7a2015-04-23 19:42:292350 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]861fcd52009-08-26 02:33:462351
danakj1fd259a02016-04-16 03:17:092352 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2353 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:412354 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:272355
[email protected]861fcd52009-08-26 02:33:462356 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:232357 MockWrite(
2358 "GET / HTTP/1.1\r\n"
2359 "Host: www.example.org\r\n"
2360 "Connection: keep-alive\r\n\r\n"),
[email protected]861fcd52009-08-26 02:33:462361 };
2362
2363 MockRead data_reads[] = {
2364 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2365 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2366 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2367 // Large content-length -- won't matter, as connection will be reset.
2368 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062369 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:462370 };
2371
[email protected]31a2bfe2010-02-09 08:03:392372 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2373 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:072374 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:412375 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:462376
[email protected]49639fa2011-12-20 23:22:412377 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012378 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]861fcd52009-08-26 02:33:462379
2380 rv = callback.WaitForResult();
2381 EXPECT_EQ(0, rv);
2382
sclittlefb249892015-09-10 21:33:222383 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2384 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2385 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
[email protected]b8015c42013-12-24 15:18:192386 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2387
[email protected]861fcd52009-08-26 02:33:462388 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522389 ASSERT_TRUE(response);
2390 EXPECT_FALSE(response->auth_challenge);
[email protected]861fcd52009-08-26 02:33:462391}
2392
[email protected]2d2697f92009-02-18 21:00:322393// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2394// connection.
bncd16676a2016-07-20 16:23:012395TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
mmenkecc2298e2015-12-07 18:20:182396 // On the second pass, the body read of the auth challenge is synchronous, so
2397 // IsConnectedAndIdle returns false. The socket should still be drained and
2398 // reused. See http://crbug.com/544255.
2399 for (int i = 0; i < 2; ++i) {
2400 HttpRequestInfo request;
2401 request.method = "GET";
2402 request.url = GURL("http://www.example.org/");
2403 request.load_flags = 0;
[email protected]2d2697f92009-02-18 21:00:322404
mmenkecc2298e2015-12-07 18:20:182405 TestNetLog log;
2406 session_deps_.net_log = &log;
danakj1fd259a02016-04-16 03:17:092407 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272408
mmenkecc2298e2015-12-07 18:20:182409 MockWrite data_writes[] = {
2410 MockWrite(ASYNC, 0,
2411 "GET / HTTP/1.1\r\n"
2412 "Host: www.example.org\r\n"
2413 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322414
mmenkecc2298e2015-12-07 18:20:182415 // After calling trans->RestartWithAuth(), this is the request we should
2416 // be issuing -- the final header line contains the credentials.
2417 MockWrite(ASYNC, 6,
2418 "GET / HTTP/1.1\r\n"
2419 "Host: www.example.org\r\n"
2420 "Connection: keep-alive\r\n"
2421 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2422 };
[email protected]2d2697f92009-02-18 21:00:322423
mmenkecc2298e2015-12-07 18:20:182424 MockRead data_reads[] = {
2425 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
2426 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2427 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2428 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
2429 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
[email protected]2d2697f92009-02-18 21:00:322430
mmenkecc2298e2015-12-07 18:20:182431 // Lastly, the server responds with the actual content.
2432 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
2433 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
2434 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
2435 MockRead(ASYNC, 10, "Hello"),
2436 };
[email protected]2d2697f92009-02-18 21:00:322437
mmenkecc2298e2015-12-07 18:20:182438 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
2439 arraysize(data_writes));
2440 data.set_busy_before_sync_reads(true);
2441 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]2d0a4f92011-05-05 16:38:462442
mmenkecc2298e2015-12-07 18:20:182443 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322444
danakj1fd259a02016-04-16 03:17:092445 std::unique_ptr<HttpTransaction> trans(
mmenkecc2298e2015-12-07 18:20:182446 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2447 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012448 ASSERT_THAT(callback1.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322449
mmenkecc2298e2015-12-07 18:20:182450 LoadTimingInfo load_timing_info1;
2451 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2452 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
[email protected]2d2697f92009-02-18 21:00:322453
mmenkecc2298e2015-12-07 18:20:182454 const HttpResponseInfo* response = trans->GetResponseInfo();
2455 ASSERT_TRUE(response);
2456 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322457
mmenkecc2298e2015-12-07 18:20:182458 TestCompletionCallback callback2;
[email protected]58e32bb2013-01-21 18:23:252459
mmenkecc2298e2015-12-07 18:20:182460 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
2461 callback2.callback());
robpercival214763f2016-07-01 23:27:012462 ASSERT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:322463
mmenkecc2298e2015-12-07 18:20:182464 LoadTimingInfo load_timing_info2;
2465 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2466 TestLoadTimingReused(load_timing_info2);
2467 // The load timing after restart should have the same socket ID, and times
2468 // those of the first load timing.
2469 EXPECT_LE(load_timing_info1.receive_headers_end,
2470 load_timing_info2.send_start);
2471 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]2d2697f92009-02-18 21:00:322472
mmenkecc2298e2015-12-07 18:20:182473 response = trans->GetResponseInfo();
2474 ASSERT_TRUE(response);
2475 EXPECT_FALSE(response->auth_challenge);
2476 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322477
mmenkecc2298e2015-12-07 18:20:182478 std::string response_data;
robpercival214763f2016-07-01 23:27:012479 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d2697f92009-02-18 21:00:322480
mmenkecc2298e2015-12-07 18:20:182481 int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes));
2482 EXPECT_EQ(writes_size, trans->GetTotalSentBytes());
2483 int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
2484 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2485 }
[email protected]2d2697f92009-02-18 21:00:322486}
2487
2488// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2489// connection and with no response body to drain.
bncd16676a2016-07-20 16:23:012490TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:422491 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322492 request.method = "GET";
bncce36dca22015-04-21 22:11:232493 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322494 request.load_flags = 0;
2495
danakj1fd259a02016-04-16 03:17:092496 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272497
[email protected]2d2697f92009-02-18 21:00:322498 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232499 MockWrite(
2500 "GET / HTTP/1.1\r\n"
2501 "Host: www.example.org\r\n"
2502 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322503
bncce36dca22015-04-21 22:11:232504 // After calling trans->RestartWithAuth(), this is the request we should
2505 // be issuing -- the final header line contains the credentials.
2506 MockWrite(
2507 "GET / HTTP/1.1\r\n"
2508 "Host: www.example.org\r\n"
2509 "Connection: keep-alive\r\n"
2510 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322511 };
2512
[email protected]2d2697f92009-02-18 21:00:322513 MockRead data_reads1[] = {
2514 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2515 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:312516 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:322517
2518 // Lastly, the server responds with the actual content.
2519 MockRead("HTTP/1.1 200 OK\r\n"),
2520 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502521 MockRead("Content-Length: 5\r\n\r\n"),
2522 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322523 };
2524
[email protected]2d0a4f92011-05-05 16:38:462525 // An incorrect reconnect would cause this to be read.
2526 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062527 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462528 };
2529
[email protected]31a2bfe2010-02-09 08:03:392530 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2531 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462532 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2533 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072534 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2535 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322536
[email protected]49639fa2011-12-20 23:22:412537 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322538
danakj1fd259a02016-04-16 03:17:092539 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502540 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412541 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012542 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:322543
2544 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012545 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:322546
[email protected]1c773ea12009-04-28 19:58:422547 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522548 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:042549 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322550
[email protected]49639fa2011-12-20 23:22:412551 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322552
[email protected]49639fa2011-12-20 23:22:412553 rv = trans->RestartWithAuth(
2554 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012555 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:322556
2557 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012558 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:322559
2560 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522561 ASSERT_TRUE(response);
2562 EXPECT_FALSE(response->auth_challenge);
[email protected]0b0bf032010-09-21 18:08:502563 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322564}
2565
2566// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2567// connection and with a large response body to drain.
bncd16676a2016-07-20 16:23:012568TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:422569 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:322570 request.method = "GET";
bncce36dca22015-04-21 22:11:232571 request.url = GURL("http://www.example.org/");
[email protected]2d2697f92009-02-18 21:00:322572 request.load_flags = 0;
2573
danakj1fd259a02016-04-16 03:17:092574 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272575
[email protected]2d2697f92009-02-18 21:00:322576 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232577 MockWrite(
2578 "GET / HTTP/1.1\r\n"
2579 "Host: www.example.org\r\n"
2580 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322581
bncce36dca22015-04-21 22:11:232582 // After calling trans->RestartWithAuth(), this is the request we should
2583 // be issuing -- the final header line contains the credentials.
2584 MockWrite(
2585 "GET / HTTP/1.1\r\n"
2586 "Host: www.example.org\r\n"
2587 "Connection: keep-alive\r\n"
2588 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:322589 };
2590
2591 // Respond with 5 kb of response body.
2592 std::string large_body_string("Unauthorized");
2593 large_body_string.append(5 * 1024, ' ');
2594 large_body_string.append("\r\n");
2595
2596 MockRead data_reads1[] = {
2597 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2598 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2599 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2600 // 5134 = 12 + 5 * 1024 + 2
2601 MockRead("Content-Length: 5134\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062602 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:322603
2604 // Lastly, the server responds with the actual content.
2605 MockRead("HTTP/1.1 200 OK\r\n"),
2606 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502607 MockRead("Content-Length: 5\r\n\r\n"),
2608 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:322609 };
2610
[email protected]2d0a4f92011-05-05 16:38:462611 // An incorrect reconnect would cause this to be read.
2612 MockRead data_reads2[] = {
[email protected]8ddf8322012-02-23 18:08:062613 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:462614 };
2615
[email protected]31a2bfe2010-02-09 08:03:392616 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2617 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:462618 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2619 NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:072620 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2621 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:322622
[email protected]49639fa2011-12-20 23:22:412623 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:322624
danakj1fd259a02016-04-16 03:17:092625 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502626 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412627 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012628 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:322629
2630 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012631 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:322632
[email protected]1c773ea12009-04-28 19:58:422633 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522634 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:042635 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:322636
[email protected]49639fa2011-12-20 23:22:412637 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:322638
[email protected]49639fa2011-12-20 23:22:412639 rv = trans->RestartWithAuth(
2640 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012641 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d2697f92009-02-18 21:00:322642
2643 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012644 EXPECT_THAT(rv, IsOk());
[email protected]2d2697f92009-02-18 21:00:322645
2646 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522647 ASSERT_TRUE(response);
2648 EXPECT_FALSE(response->auth_challenge);
[email protected]0b0bf032010-09-21 18:08:502649 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:322650}
2651
2652// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:312653// connection, but the server gets impatient and closes the connection.
bncd16676a2016-07-20 16:23:012654TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:312655 HttpRequestInfo request;
2656 request.method = "GET";
bncce36dca22015-04-21 22:11:232657 request.url = GURL("http://www.example.org/");
[email protected]11203f012009-11-12 23:02:312658 request.load_flags = 0;
2659
danakj1fd259a02016-04-16 03:17:092660 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272661
[email protected]11203f012009-11-12 23:02:312662 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:232663 MockWrite(
2664 "GET / HTTP/1.1\r\n"
2665 "Host: www.example.org\r\n"
2666 "Connection: keep-alive\r\n\r\n"),
2667 // This simulates the seemingly successful write to a closed connection
2668 // if the bug is not fixed.
2669 MockWrite(
2670 "GET / HTTP/1.1\r\n"
2671 "Host: www.example.org\r\n"
2672 "Connection: keep-alive\r\n"
2673 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312674 };
2675
2676 MockRead data_reads1[] = {
2677 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2678 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2679 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2680 MockRead("Content-Length: 14\r\n\r\n"),
2681 // Tell MockTCPClientSocket to simulate the server closing the connection.
[email protected]8ddf8322012-02-23 18:08:062682 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:312683 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:062684 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:312685 };
2686
2687 // After calling trans->RestartWithAuth(), this is the request we should
2688 // be issuing -- the final header line contains the credentials.
2689 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:232690 MockWrite(
2691 "GET / HTTP/1.1\r\n"
2692 "Host: www.example.org\r\n"
2693 "Connection: keep-alive\r\n"
2694 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]11203f012009-11-12 23:02:312695 };
2696
2697 // Lastly, the server responds with the actual content.
2698 MockRead data_reads2[] = {
2699 MockRead("HTTP/1.1 200 OK\r\n"),
2700 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:502701 MockRead("Content-Length: 5\r\n\r\n"),
2702 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:312703 };
2704
[email protected]31a2bfe2010-02-09 08:03:392705 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2706 data_writes1, arraysize(data_writes1));
2707 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2708 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:072709 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2710 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]11203f012009-11-12 23:02:312711
[email protected]49639fa2011-12-20 23:22:412712 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:312713
danakj1fd259a02016-04-16 03:17:092714 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502715 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:412716 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:012717 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:312718
2719 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012720 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:312721
2722 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522723 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:042724 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:312725
[email protected]49639fa2011-12-20 23:22:412726 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:312727
[email protected]49639fa2011-12-20 23:22:412728 rv = trans->RestartWithAuth(
2729 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012730 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]11203f012009-11-12 23:02:312731
2732 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012733 EXPECT_THAT(rv, IsOk());
[email protected]11203f012009-11-12 23:02:312734
2735 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522736 ASSERT_TRUE(response);
2737 EXPECT_FALSE(response->auth_challenge);
[email protected]0b0bf032010-09-21 18:08:502738 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:312739}
2740
[email protected]394816e92010-08-03 07:38:592741// Test the request-challenge-retry sequence for basic auth, over a connection
2742// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:012743TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
ttuttle34f63b52015-03-05 04:33:012744 HttpRequestInfo request;
2745 request.method = "GET";
bncce36dca22015-04-21 22:11:232746 request.url = GURL("https://www.example.org/");
ttuttle34f63b52015-03-05 04:33:012747 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292748 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:012749
2750 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032751 session_deps_.proxy_service =
2752 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512753 BoundTestNetLog log;
ttuttle34f63b52015-03-05 04:33:012754 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:092755 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:012756
2757 // Since we have proxy, should try to establish tunnel.
2758 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542759 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172760 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542761 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:012762 };
2763
mmenkee71e15332015-10-07 16:39:542764 // The proxy responds to the connect with a 407, using a non-persistent
ttuttle34f63b52015-03-05 04:33:012765 // connection.
2766 MockRead data_reads1[] = {
2767 // No credentials.
2768 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2769 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
mmenkee71e15332015-10-07 16:39:542770 };
ttuttle34f63b52015-03-05 04:33:012771
mmenkee71e15332015-10-07 16:39:542772 // Since the first connection couldn't be reused, need to establish another
2773 // once given credentials.
2774 MockWrite data_writes2[] = {
2775 // After calling trans->RestartWithAuth(), this is the request we should
2776 // be issuing -- the final header line contains the credentials.
2777 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172778 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542779 "Proxy-Connection: keep-alive\r\n"
2780 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2781
2782 MockWrite("GET / HTTP/1.1\r\n"
2783 "Host: www.example.org\r\n"
2784 "Connection: keep-alive\r\n\r\n"),
2785 };
2786
2787 MockRead data_reads2[] = {
ttuttle34f63b52015-03-05 04:33:012788 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2789
2790 MockRead("HTTP/1.1 200 OK\r\n"),
2791 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2792 MockRead("Content-Length: 5\r\n\r\n"),
2793 MockRead(SYNCHRONOUS, "hello"),
2794 };
2795
2796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2797 data_writes1, arraysize(data_writes1));
2798 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542799 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2800 data_writes2, arraysize(data_writes2));
2801 session_deps_.socket_factory->AddSocketDataProvider(&data2);
ttuttle34f63b52015-03-05 04:33:012802 SSLSocketDataProvider ssl(ASYNC, OK);
2803 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2804
2805 TestCompletionCallback callback1;
2806
danakj1fd259a02016-04-16 03:17:092807 std::unique_ptr<HttpTransaction> trans(
ttuttle34f63b52015-03-05 04:33:012808 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2809
2810 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:012811 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:012812
2813 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012814 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:462815 TestNetLogEntry::List entries;
ttuttle34f63b52015-03-05 04:33:012816 log.GetEntries(&entries);
2817 size_t pos = ExpectLogContainsSomewhere(
2818 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2819 NetLog::PHASE_NONE);
2820 ExpectLogContainsSomewhere(
2821 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2822 NetLog::PHASE_NONE);
2823
2824 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522825 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:012826 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:522827 ASSERT_TRUE(response->headers);
ttuttle34f63b52015-03-05 04:33:012828 EXPECT_EQ(407, response->headers->response_code());
2829 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
2830 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2831
2832 LoadTimingInfo load_timing_info;
2833 // CONNECT requests and responses are handled at the connect job level, so
2834 // the transaction does not yet have a connection.
2835 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2836
2837 TestCompletionCallback callback2;
2838
2839 rv =
2840 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012841 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle34f63b52015-03-05 04:33:012842
2843 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012844 EXPECT_THAT(rv, IsOk());
ttuttle34f63b52015-03-05 04:33:012845
2846 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522847 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:012848
2849 EXPECT_TRUE(response->headers->IsKeepAlive());
2850 EXPECT_EQ(200, response->headers->response_code());
2851 EXPECT_EQ(5, response->headers->GetContentLength());
2852 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2853
2854 // The password prompt info should not be set.
wezca1070932016-05-26 20:30:522855 EXPECT_FALSE(response->auth_challenge);
ttuttle34f63b52015-03-05 04:33:012856
2857 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2858 TestLoadTimingNotReusedWithPac(load_timing_info,
2859 CONNECT_TIMING_HAS_SSL_TIMES);
2860
2861 trans.reset();
2862 session->CloseAllConnections();
2863}
2864
2865// Test the request-challenge-retry sequence for basic auth, over a connection
2866// that requires a restart when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:012867TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
[email protected]394816e92010-08-03 07:38:592868 HttpRequestInfo request;
2869 request.method = "GET";
bncce36dca22015-04-21 22:11:232870 request.url = GURL("https://www.example.org/");
[email protected]394816e92010-08-03 07:38:592871 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:292872 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]394816e92010-08-03 07:38:592873
[email protected]cb9bf6ca2011-01-28 13:15:272874 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:032875 session_deps_.proxy_service =
2876 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:512877 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:072878 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:092879 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:272880
[email protected]394816e92010-08-03 07:38:592881 // Since we have proxy, should try to establish tunnel.
2882 MockWrite data_writes1[] = {
mmenkee71e15332015-10-07 16:39:542883 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172884 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542885 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenkee0b5c882015-08-26 20:29:112886 };
2887
mmenkee71e15332015-10-07 16:39:542888 // The proxy responds to the connect with a 407, using a non-persistent
mmenke0fd148d2015-09-30 23:00:082889 // connection.
2890 MockRead data_reads1[] = {
mmenkee71e15332015-10-07 16:39:542891 // No credentials.
2892 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2893 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2894 MockRead("Proxy-Connection: close\r\n\r\n"),
2895 };
mmenkee0b5c882015-08-26 20:29:112896
mmenkee71e15332015-10-07 16:39:542897 MockWrite data_writes2[] = {
2898 // After calling trans->RestartWithAuth(), this is the request we should
2899 // be issuing -- the final header line contains the credentials.
2900 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:172901 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:542902 "Proxy-Connection: keep-alive\r\n"
2903 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
mmenke0fd148d2015-09-30 23:00:082904
mmenkee71e15332015-10-07 16:39:542905 MockWrite("GET / HTTP/1.1\r\n"
2906 "Host: www.example.org\r\n"
2907 "Connection: keep-alive\r\n\r\n"),
2908 };
2909
2910 MockRead data_reads2[] = {
2911 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2912
2913 MockRead("HTTP/1.1 200 OK\r\n"),
2914 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2915 MockRead("Content-Length: 5\r\n\r\n"),
2916 MockRead(SYNCHRONOUS, "hello"),
[email protected]394816e92010-08-03 07:38:592917 };
2918
2919 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2920 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:072921 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenkee71e15332015-10-07 16:39:542922 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2923 data_writes2, arraysize(data_writes2));
2924 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8ddf8322012-02-23 18:08:062925 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:072926 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]394816e92010-08-03 07:38:592927
[email protected]49639fa2011-12-20 23:22:412928 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:592929
danakj1fd259a02016-04-16 03:17:092930 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:502931 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:502932
[email protected]49639fa2011-12-20 23:22:412933 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:012934 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:592935
2936 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:012937 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:462938 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:402939 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:592940 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402941 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:592942 NetLog::PHASE_NONE);
2943 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402944 entries, pos,
[email protected]394816e92010-08-03 07:38:592945 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2946 NetLog::PHASE_NONE);
2947
2948 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522949 ASSERT_TRUE(response);
ttuttle34f63b52015-03-05 04:33:012950 EXPECT_FALSE(response->headers->IsKeepAlive());
wezca1070932016-05-26 20:30:522951 ASSERT_TRUE(response->headers);
[email protected]394816e92010-08-03 07:38:592952 EXPECT_EQ(407, response->headers->response_code());
2953 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042954 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:592955
[email protected]029c83b62013-01-24 05:28:202956 LoadTimingInfo load_timing_info;
2957 // CONNECT requests and responses are handled at the connect job level, so
2958 // the transaction does not yet have a connection.
2959 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2960
[email protected]49639fa2011-12-20 23:22:412961 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:592962
[email protected]49639fa2011-12-20 23:22:412963 rv = trans->RestartWithAuth(
2964 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:012965 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]394816e92010-08-03 07:38:592966
2967 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:012968 EXPECT_THAT(rv, IsOk());
[email protected]394816e92010-08-03 07:38:592969
2970 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:522971 ASSERT_TRUE(response);
[email protected]394816e92010-08-03 07:38:592972
2973 EXPECT_TRUE(response->headers->IsKeepAlive());
2974 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:502975 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:592976 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2977
2978 // The password prompt info should not be set.
wezca1070932016-05-26 20:30:522979 EXPECT_FALSE(response->auth_challenge);
[email protected]0b0bf032010-09-21 18:08:502980
[email protected]029c83b62013-01-24 05:28:202981 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2982 TestLoadTimingNotReusedWithPac(load_timing_info,
2983 CONNECT_TIMING_HAS_SSL_TIMES);
2984
[email protected]0b0bf032010-09-21 18:08:502985 trans.reset();
[email protected]102e27c2011-02-23 01:01:312986 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:592987}
2988
[email protected]11203f012009-11-12 23:02:312989// Test the request-challenge-retry sequence for basic auth, over a keep-alive
ttuttle34f63b52015-03-05 04:33:012990// proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:012991TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
mmenked39192ee2015-12-09 00:57:232992 // On the second pass, the body read of the auth challenge is synchronous, so
2993 // IsConnectedAndIdle returns false. The socket should still be drained and
2994 // reused. See http://crbug.com/544255.
2995 for (int i = 0; i < 2; ++i) {
2996 HttpRequestInfo request;
2997 request.method = "GET";
2998 request.url = GURL("https://www.example.org/");
2999 // Ensure that proxy authentication is attempted even
3000 // when the no authentication data flag is set.
3001 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
ttuttle34f63b52015-03-05 04:33:013002
mmenked39192ee2015-12-09 00:57:233003 // Configure against proxy server "myproxy:70".
3004 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
3005 BoundTestNetLog log;
3006 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093007 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle34f63b52015-03-05 04:33:013008
danakj1fd259a02016-04-16 03:17:093009 std::unique_ptr<HttpTransaction> trans(
mmenked39192ee2015-12-09 00:57:233010 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ttuttle34f63b52015-03-05 04:33:013011
mmenked39192ee2015-12-09 00:57:233012 // Since we have proxy, should try to establish tunnel.
3013 MockWrite data_writes1[] = {
3014 MockWrite(ASYNC, 0,
3015 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3016 "Host: www.example.org:443\r\n"
3017 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle34f63b52015-03-05 04:33:013018
mmenked39192ee2015-12-09 00:57:233019 // After calling trans->RestartWithAuth(), this is the request we should
3020 // be issuing -- the final header line contains the credentials.
3021 MockWrite(ASYNC, 3,
3022 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3023 "Host: www.example.org:443\r\n"
3024 "Proxy-Connection: keep-alive\r\n"
3025 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3026 };
ttuttle34f63b52015-03-05 04:33:013027
mmenked39192ee2015-12-09 00:57:233028 // The proxy responds to the connect with a 407, using a persistent
3029 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3030 MockRead data_reads1[] = {
3031 // No credentials.
3032 MockRead(ASYNC, 1,
3033 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3034 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3035 "Proxy-Connection: keep-alive\r\n"
3036 "Content-Length: 10\r\n\r\n"),
3037 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
ttuttle34f63b52015-03-05 04:33:013038
mmenked39192ee2015-12-09 00:57:233039 // Wrong credentials (wrong password).
3040 MockRead(ASYNC, 4,
3041 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3042 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3043 "Proxy-Connection: keep-alive\r\n"
3044 "Content-Length: 10\r\n\r\n"),
3045 // No response body because the test stops reading here.
3046 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3047 };
ttuttle34f63b52015-03-05 04:33:013048
mmenked39192ee2015-12-09 00:57:233049 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3050 arraysize(data_writes1));
3051 data1.set_busy_before_sync_reads(true);
3052 session_deps_.socket_factory->AddSocketDataProvider(&data1);
ttuttle34f63b52015-03-05 04:33:013053
mmenked39192ee2015-12-09 00:57:233054 TestCompletionCallback callback1;
ttuttle34f63b52015-03-05 04:33:013055
mmenked39192ee2015-12-09 00:57:233056 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013057 EXPECT_THAT(callback1.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013058
mmenked39192ee2015-12-09 00:57:233059 TestNetLogEntry::List entries;
3060 log.GetEntries(&entries);
3061 size_t pos = ExpectLogContainsSomewhere(
3062 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3063 NetLog::PHASE_NONE);
3064 ExpectLogContainsSomewhere(
3065 entries, pos,
3066 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3067 NetLog::PHASE_NONE);
ttuttle34f63b52015-03-05 04:33:013068
mmenked39192ee2015-12-09 00:57:233069 const HttpResponseInfo* response = trans->GetResponseInfo();
3070 ASSERT_TRUE(response);
3071 ASSERT_TRUE(response->headers);
3072 EXPECT_TRUE(response->headers->IsKeepAlive());
3073 EXPECT_EQ(407, response->headers->response_code());
3074 EXPECT_EQ(10, response->headers->GetContentLength());
3075 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
3076 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:013077
mmenked39192ee2015-12-09 00:57:233078 TestCompletionCallback callback2;
ttuttle34f63b52015-03-05 04:33:013079
mmenked39192ee2015-12-09 00:57:233080 // Wrong password (should be "bar").
3081 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
3082 callback2.callback());
robpercival214763f2016-07-01 23:27:013083 EXPECT_THAT(callback2.GetResult(rv), IsOk());
ttuttle34f63b52015-03-05 04:33:013084
mmenked39192ee2015-12-09 00:57:233085 response = trans->GetResponseInfo();
3086 ASSERT_TRUE(response);
3087 ASSERT_TRUE(response->headers);
3088 EXPECT_TRUE(response->headers->IsKeepAlive());
3089 EXPECT_EQ(407, response->headers->response_code());
3090 EXPECT_EQ(10, response->headers->GetContentLength());
3091 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
3092 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
ttuttle34f63b52015-03-05 04:33:013093
mmenked39192ee2015-12-09 00:57:233094 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3095 // out of scope.
3096 session->CloseAllConnections();
3097 }
ttuttle34f63b52015-03-05 04:33:013098}
3099
3100// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3101// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
bncd16676a2016-07-20 16:23:013102TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
mmenked39192ee2015-12-09 00:57:233103 // On the second pass, the body read of the auth challenge is synchronous, so
3104 // IsConnectedAndIdle returns false. The socket should still be drained and
3105 // reused. See http://crbug.com/544255.
3106 for (int i = 0; i < 2; ++i) {
3107 HttpRequestInfo request;
3108 request.method = "GET";
3109 request.url = GURL("https://www.example.org/");
3110 // Ensure that proxy authentication is attempted even
3111 // when the no authentication data flag is set.
3112 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3113
3114 // Configure against proxy server "myproxy:70".
3115 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
3116 BoundTestNetLog log;
3117 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093118 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenked39192ee2015-12-09 00:57:233119
danakj1fd259a02016-04-16 03:17:093120 std::unique_ptr<HttpTransaction> trans(
mmenked39192ee2015-12-09 00:57:233121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3122
3123 // Since we have proxy, should try to establish tunnel.
3124 MockWrite data_writes1[] = {
3125 MockWrite(ASYNC, 0,
3126 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3127 "Host: www.example.org:443\r\n"
3128 "Proxy-Connection: keep-alive\r\n\r\n"),
3129
3130 // After calling trans->RestartWithAuth(), this is the request we should
3131 // be issuing -- the final header line contains the credentials.
3132 MockWrite(ASYNC, 3,
3133 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3134 "Host: www.example.org:443\r\n"
3135 "Proxy-Connection: keep-alive\r\n"
3136 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3137 };
3138
3139 // The proxy responds to the connect with a 407, using a persistent
3140 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3141 MockRead data_reads1[] = {
3142 // No credentials.
3143 MockRead(ASYNC, 1,
3144 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3145 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3146 "Content-Length: 10\r\n\r\n"),
3147 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3148
3149 // Wrong credentials (wrong password).
3150 MockRead(ASYNC, 4,
3151 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3152 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3153 "Content-Length: 10\r\n\r\n"),
3154 // No response body because the test stops reading here.
3155 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3156 };
3157
3158 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3159 arraysize(data_writes1));
3160 data1.set_busy_before_sync_reads(true);
3161 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3162
3163 TestCompletionCallback callback1;
3164
3165 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013166 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233167
3168 TestNetLogEntry::List entries;
3169 log.GetEntries(&entries);
3170 size_t pos = ExpectLogContainsSomewhere(
3171 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3172 NetLog::PHASE_NONE);
3173 ExpectLogContainsSomewhere(
3174 entries, pos,
3175 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3176 NetLog::PHASE_NONE);
3177
3178 const HttpResponseInfo* response = trans->GetResponseInfo();
3179 ASSERT_TRUE(response);
3180 ASSERT_TRUE(response->headers);
3181 EXPECT_TRUE(response->headers->IsKeepAlive());
3182 EXPECT_EQ(407, response->headers->response_code());
3183 EXPECT_EQ(10, response->headers->GetContentLength());
3184 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3185 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3186
3187 TestCompletionCallback callback2;
3188
3189 // Wrong password (should be "bar").
3190 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz),
3191 callback2.callback());
robpercival214763f2016-07-01 23:27:013192 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233193
3194 response = trans->GetResponseInfo();
3195 ASSERT_TRUE(response);
3196 ASSERT_TRUE(response->headers);
3197 EXPECT_TRUE(response->headers->IsKeepAlive());
3198 EXPECT_EQ(407, response->headers->response_code());
3199 EXPECT_EQ(10, response->headers->GetContentLength());
3200 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3201 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3202
3203 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
3204 // out of scope.
3205 session->CloseAllConnections();
3206 }
3207}
3208
3209// Test the request-challenge-retry sequence for basic auth, over a keep-alive
3210// proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
3211// the case the server sends extra data on the original socket, so it can't be
3212// reused.
bncd16676a2016-07-20 16:23:013213TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
[email protected]cb9bf6ca2011-01-28 13:15:273214 HttpRequestInfo request;
3215 request.method = "GET";
bncce36dca22015-04-21 22:11:233216 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273217 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:293218 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]cb9bf6ca2011-01-28 13:15:273219
[email protected]2d2697f92009-02-18 21:00:323220 // Configure against proxy server "myproxy:70".
mmenked39192ee2015-12-09 00:57:233221 session_deps_.proxy_service =
3222 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:513223 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073224 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093225 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2d2697f92009-02-18 21:00:323226
[email protected]2d2697f92009-02-18 21:00:323227 // Since we have proxy, should try to establish tunnel.
3228 MockWrite data_writes1[] = {
mmenked39192ee2015-12-09 00:57:233229 MockWrite(ASYNC, 0,
3230 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173231 "Host: www.example.org:443\r\n"
3232 "Proxy-Connection: keep-alive\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233233 };
[email protected]2d2697f92009-02-18 21:00:323234
mmenked39192ee2015-12-09 00:57:233235 // The proxy responds to the connect with a 407, using a persistent, but sends
3236 // extra data, so the socket cannot be reused.
3237 MockRead data_reads1[] = {
3238 // No credentials.
3239 MockRead(ASYNC, 1,
3240 "HTTP/1.1 407 Proxy Authentication Required\r\n"
3241 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3242 "Content-Length: 10\r\n\r\n"),
3243 MockRead(SYNCHRONOUS, 2, "0123456789"),
3244 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
3245 };
3246
3247 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:233248 // After calling trans->RestartWithAuth(), this is the request we should
3249 // be issuing -- the final header line contains the credentials.
mmenked39192ee2015-12-09 00:57:233250 MockWrite(ASYNC, 0,
3251 "CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173252 "Host: www.example.org:443\r\n"
3253 "Proxy-Connection: keep-alive\r\n"
mmenked39192ee2015-12-09 00:57:233254 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3255
3256 MockWrite(ASYNC, 2,
3257 "GET / HTTP/1.1\r\n"
3258 "Host: www.example.org\r\n"
3259 "Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323260 };
3261
mmenked39192ee2015-12-09 00:57:233262 MockRead data_reads2[] = {
3263 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:323264
mmenked39192ee2015-12-09 00:57:233265 MockRead(ASYNC, 3,
3266 "HTTP/1.1 200 OK\r\n"
3267 "Content-Type: text/html; charset=iso-8859-1\r\n"
3268 "Content-Length: 5\r\n\r\n"),
3269 // No response body because the test stops reading here.
3270 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
[email protected]2d2697f92009-02-18 21:00:323271 };
3272
mmenked39192ee2015-12-09 00:57:233273 SequencedSocketData data1(data_reads1, arraysize(data_reads1), data_writes1,
3274 arraysize(data_writes1));
3275 data1.set_busy_before_sync_reads(true);
[email protected]bb88e1d32013-05-03 23:11:073276 session_deps_.socket_factory->AddSocketDataProvider(&data1);
mmenked39192ee2015-12-09 00:57:233277 SequencedSocketData data2(data_reads2, arraysize(data_reads2), data_writes2,
3278 arraysize(data_writes2));
3279 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3280 SSLSocketDataProvider ssl(ASYNC, OK);
3281 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d2697f92009-02-18 21:00:323282
[email protected]49639fa2011-12-20 23:22:413283 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:323284
danakj1fd259a02016-04-16 03:17:093285 std::unique_ptr<HttpTransaction> trans(
mmenked39192ee2015-12-09 00:57:233286 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d2697f92009-02-18 21:00:323287
mmenked39192ee2015-12-09 00:57:233288 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013289 EXPECT_THAT(callback1.GetResult(rv), IsOk());
mmenked39192ee2015-12-09 00:57:233290
mmenke43758e62015-05-04 21:09:463291 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403292 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:393293 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403294 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:393295 NetLog::PHASE_NONE);
3296 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403297 entries, pos,
[email protected]dbb83db2010-05-11 18:13:393298 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3299 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:323300
[email protected]1c773ea12009-04-28 19:58:423301 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243302 ASSERT_TRUE(response);
3303 ASSERT_TRUE(response->headers);
[email protected]2d2697f92009-02-18 21:00:323304 EXPECT_TRUE(response->headers->IsKeepAlive());
3305 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423306 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:043307 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:323308
mmenked39192ee2015-12-09 00:57:233309 LoadTimingInfo load_timing_info;
3310 // CONNECT requests and responses are handled at the connect job level, so
3311 // the transaction does not yet have a connection.
3312 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3313
[email protected]49639fa2011-12-20 23:22:413314 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:323315
mmenked39192ee2015-12-09 00:57:233316 rv =
3317 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:013318 EXPECT_THAT(callback2.GetResult(rv), IsOk());
[email protected]2d2697f92009-02-18 21:00:323319
[email protected]2d2697f92009-02-18 21:00:323320 EXPECT_TRUE(response->headers->IsKeepAlive());
mmenked39192ee2015-12-09 00:57:233321 EXPECT_EQ(200, response->headers->response_code());
3322 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:423323 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]e772db3f2010-07-12 18:11:133324
mmenked39192ee2015-12-09 00:57:233325 // The password prompt info should not be set.
3326 EXPECT_FALSE(response->auth_challenge);
3327
3328 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3329 TestLoadTimingNotReusedWithPac(load_timing_info,
3330 CONNECT_TIMING_HAS_SSL_TIMES);
3331
3332 trans.reset();
[email protected]102e27c2011-02-23 01:01:313333 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:323334}
3335
mmenkee71e15332015-10-07 16:39:543336// Test the case a proxy closes a socket while the challenge body is being
3337// drained.
bncd16676a2016-07-20 16:23:013338TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
mmenkee71e15332015-10-07 16:39:543339 HttpRequestInfo request;
3340 request.method = "GET";
3341 request.url = GURL("https://www.example.org/");
3342 // Ensure that proxy authentication is attempted even
3343 // when the no authentication data flag is set.
3344 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
3345
3346 // Configure against proxy server "myproxy:70".
3347 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
danakj1fd259a02016-04-16 03:17:093348 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenkee71e15332015-10-07 16:39:543349
danakj1fd259a02016-04-16 03:17:093350 std::unique_ptr<HttpTransaction> trans(
mmenkee71e15332015-10-07 16:39:543351 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3352
3353 // Since we have proxy, should try to establish tunnel.
3354 MockWrite data_writes1[] = {
3355 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173356 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543357 "Proxy-Connection: keep-alive\r\n\r\n"),
3358 };
3359
3360 // The proxy responds to the connect with a 407, using a persistent
3361 // connection.
3362 MockRead data_reads1[] = {
3363 // No credentials.
3364 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3365 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3366 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
3367 // Server hands up in the middle of the body.
3368 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
3369 };
3370
3371 MockWrite data_writes2[] = {
3372 // After calling trans->RestartWithAuth(), this is the request we should
3373 // be issuing -- the final header line contains the credentials.
3374 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173375 "Host: www.example.org:443\r\n"
mmenkee71e15332015-10-07 16:39:543376 "Proxy-Connection: keep-alive\r\n"
3377 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3378
3379 MockWrite("GET / HTTP/1.1\r\n"
3380 "Host: www.example.org\r\n"
3381 "Connection: keep-alive\r\n\r\n"),
3382 };
3383
3384 MockRead data_reads2[] = {
3385 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3386
3387 MockRead("HTTP/1.1 200 OK\r\n"),
3388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3389 MockRead("Content-Length: 5\r\n\r\n"),
3390 MockRead(SYNCHRONOUS, "hello"),
3391 };
3392
3393 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3394 data_writes1, arraysize(data_writes1));
3395 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3396 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3397 data_writes2, arraysize(data_writes2));
3398 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3399 SSLSocketDataProvider ssl(ASYNC, OK);
3400 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3401
3402 TestCompletionCallback callback;
3403
3404 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013405 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543406
3407 const HttpResponseInfo* response = trans->GetResponseInfo();
3408 ASSERT_TRUE(response);
3409 ASSERT_TRUE(response->headers);
3410 EXPECT_TRUE(response->headers->IsKeepAlive());
3411 EXPECT_EQ(407, response->headers->response_code());
3412 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3413
3414 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
robpercival214763f2016-07-01 23:27:013415 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenkee71e15332015-10-07 16:39:543416
3417 response = trans->GetResponseInfo();
3418 ASSERT_TRUE(response);
3419 ASSERT_TRUE(response->headers);
3420 EXPECT_TRUE(response->headers->IsKeepAlive());
3421 EXPECT_EQ(200, response->headers->response_code());
3422 std::string body;
robpercival214763f2016-07-01 23:27:013423 EXPECT_THAT(ReadTransaction(trans.get(), &body), IsOk());
mmenkee71e15332015-10-07 16:39:543424 EXPECT_EQ("hello", body);
3425}
3426
[email protected]a8e9b162009-03-12 00:06:443427// Test that we don't read the response body when we fail to establish a tunnel,
3428// even if the user cancels the proxy's auth attempt.
bncd16676a2016-07-20 16:23:013429TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273430 HttpRequestInfo request;
3431 request.method = "GET";
bncce36dca22015-04-21 22:11:233432 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273433 request.load_flags = 0;
3434
[email protected]a8e9b162009-03-12 00:06:443435 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033436 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]a8e9b162009-03-12 00:06:443437
danakj1fd259a02016-04-16 03:17:093438 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]a8e9b162009-03-12 00:06:443439
danakj1fd259a02016-04-16 03:17:093440 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]a8e9b162009-03-12 00:06:443442
[email protected]a8e9b162009-03-12 00:06:443443 // Since we have proxy, should try to establish tunnel.
3444 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173445 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3446 "Host: www.example.org:443\r\n"
3447 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:443448 };
3449
3450 // The proxy responds to the connect with a 407.
3451 MockRead data_reads[] = {
ttuttle7933c112015-01-06 00:55:243452 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3453 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3454 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233455 MockRead("0123456789"),
ttuttle7933c112015-01-06 00:55:243456 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]a8e9b162009-03-12 00:06:443457 };
3458
[email protected]31a2bfe2010-02-09 08:03:393459 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3460 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:073461 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:443462
[email protected]49639fa2011-12-20 23:22:413463 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:443464
[email protected]49639fa2011-12-20 23:22:413465 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013466 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]a8e9b162009-03-12 00:06:443467
3468 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013469 EXPECT_THAT(rv, IsOk());
[email protected]a8e9b162009-03-12 00:06:443470
[email protected]1c773ea12009-04-28 19:58:423471 const HttpResponseInfo* response = trans->GetResponseInfo();
ttuttle7933c112015-01-06 00:55:243472 ASSERT_TRUE(response);
3473 ASSERT_TRUE(response->headers);
[email protected]a8e9b162009-03-12 00:06:443474 EXPECT_TRUE(response->headers->IsKeepAlive());
3475 EXPECT_EQ(407, response->headers->response_code());
[email protected]1c773ea12009-04-28 19:58:423476 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:443477
3478 std::string response_data;
3479 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:013480 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]e60e47a2010-07-14 03:37:183481
3482 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:313483 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:443484}
3485
ttuttle7933c112015-01-06 00:55:243486// Test that we don't pass extraneous headers from the proxy's response to the
3487// caller when the proxy responds to CONNECT with 407.
bncd16676a2016-07-20 16:23:013488TEST_F(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
ttuttle7933c112015-01-06 00:55:243489 HttpRequestInfo request;
3490 request.method = "GET";
bncce36dca22015-04-21 22:11:233491 request.url = GURL("https://www.example.org/");
ttuttle7933c112015-01-06 00:55:243492 request.load_flags = 0;
3493
3494 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:033495 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
ttuttle7933c112015-01-06 00:55:243496
danakj1fd259a02016-04-16 03:17:093497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
ttuttle7933c112015-01-06 00:55:243498
danakj1fd259a02016-04-16 03:17:093499 std::unique_ptr<HttpTransaction> trans(
ttuttle7933c112015-01-06 00:55:243500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3501
3502 // Since we have proxy, should try to establish tunnel.
3503 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:173504 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3505 "Host: www.example.org:443\r\n"
3506 "Proxy-Connection: keep-alive\r\n\r\n"),
ttuttle7933c112015-01-06 00:55:243507 };
3508
3509 // The proxy responds to the connect with a 407.
3510 MockRead data_reads[] = {
3511 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3512 MockRead("X-Foo: bar\r\n"),
3513 MockRead("Set-Cookie: foo=bar\r\n"),
3514 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3515 MockRead("Content-Length: 10\r\n\r\n"),
mmenked39192ee2015-12-09 00:57:233516 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
ttuttle7933c112015-01-06 00:55:243517 };
3518
3519 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
3520 arraysize(data_writes));
3521 session_deps_.socket_factory->AddSocketDataProvider(&data);
3522
3523 TestCompletionCallback callback;
3524
3525 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
ttuttle7933c112015-01-06 00:55:243527
3528 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013529 EXPECT_THAT(rv, IsOk());
ttuttle7933c112015-01-06 00:55:243530
3531 const HttpResponseInfo* response = trans->GetResponseInfo();
3532 ASSERT_TRUE(response);
3533 ASSERT_TRUE(response->headers);
3534 EXPECT_TRUE(response->headers->IsKeepAlive());
3535 EXPECT_EQ(407, response->headers->response_code());
3536 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3537 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
3538 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
3539
3540 std::string response_data;
3541 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:013542 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
ttuttle7933c112015-01-06 00:55:243543
3544 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3545 session->CloseAllConnections();
3546}
3547
[email protected]8fdbcd22010-05-05 02:54:523548// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3549// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
bncd16676a2016-07-20 16:23:013550TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:523551 HttpRequestInfo request;
3552 request.method = "GET";
bncce36dca22015-04-21 22:11:233553 request.url = GURL("http://www.example.org/");
[email protected]8fdbcd22010-05-05 02:54:523554 request.load_flags = 0;
3555
[email protected]cb9bf6ca2011-01-28 13:15:273556 // We are using a DIRECT connection (i.e. no proxy) for this session.
danakj1fd259a02016-04-16 03:17:093557 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3558 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:413559 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:273560
[email protected]8fdbcd22010-05-05 02:54:523561 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:233562 MockWrite(
3563 "GET / HTTP/1.1\r\n"
3564 "Host: www.example.org\r\n"
3565 "Connection: keep-alive\r\n\r\n"),
[email protected]8fdbcd22010-05-05 02:54:523566 };
3567
3568 MockRead data_reads1[] = {
3569 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3570 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3571 // Large content-length -- won't matter, as connection will be reset.
3572 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063573 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:523574 };
3575
3576 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3577 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073578 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8fdbcd22010-05-05 02:54:523579
[email protected]49639fa2011-12-20 23:22:413580 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:523581
[email protected]49639fa2011-12-20 23:22:413582 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013583 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8fdbcd22010-05-05 02:54:523584
3585 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:013586 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
[email protected]8fdbcd22010-05-05 02:54:523587}
3588
[email protected]7a67a8152010-11-05 18:31:103589// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3590// through a non-authenticating proxy. The request should fail with
3591// ERR_UNEXPECTED_PROXY_AUTH.
3592// Note that it is impossible to detect if an HTTP server returns a 407 through
3593// a non-authenticating proxy - there is nothing to indicate whether the
3594// response came from the proxy or the server, so it is treated as if the proxy
3595// issued the challenge.
bncd16676a2016-07-20 16:23:013596TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:273597 HttpRequestInfo request;
3598 request.method = "GET";
bncce36dca22015-04-21 22:11:233599 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:273600
rdsmith82957ad2015-09-16 19:42:033601 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:513602 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:073603 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:093604 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7a67a8152010-11-05 18:31:103605
[email protected]7a67a8152010-11-05 18:31:103606 // Since we have proxy, should try to establish tunnel.
3607 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:173608 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3609 "Host: www.example.org:443\r\n"
3610 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103611
rsleevidb16bb02015-11-12 23:47:173612 MockWrite("GET / HTTP/1.1\r\n"
3613 "Host: www.example.org\r\n"
3614 "Connection: keep-alive\r\n\r\n"),
[email protected]7a67a8152010-11-05 18:31:103615 };
3616
3617 MockRead data_reads1[] = {
3618 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3619
3620 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3621 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3622 MockRead("\r\n"),
[email protected]8ddf8322012-02-23 18:08:063623 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:103624 };
3625
3626 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3627 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:073628 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:063629 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:073630 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7a67a8152010-11-05 18:31:103631
[email protected]49639fa2011-12-20 23:22:413632 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:103633
danakj1fd259a02016-04-16 03:17:093634 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:503635 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7a67a8152010-11-05 18:31:103636
[email protected]49639fa2011-12-20 23:22:413637 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:013638 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7a67a8152010-11-05 18:31:103639
3640 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:013641 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
mmenke43758e62015-05-04 21:09:463642 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403643 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:103644 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403645 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:103646 NetLog::PHASE_NONE);
3647 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403648 entries, pos,
[email protected]7a67a8152010-11-05 18:31:103649 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3650 NetLog::PHASE_NONE);
3651}
[email protected]2df19bb2010-08-25 20:13:463652
mmenke2a1781d2015-10-07 19:25:333653// Test a proxy auth scheme that allows default credentials and a proxy server
3654// that uses non-persistent connections.
bncd16676a2016-07-20 16:23:013655TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:333656 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
3657 HttpRequestInfo request;
3658 request.method = "GET";
3659 request.url = GURL("https://www.example.org/");
3660
3661 // Configure against proxy server "myproxy:70".
3662 session_deps_.proxy_service =
3663 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3664
danakj1fd259a02016-04-16 03:17:093665 std::unique_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
mmenke2a1781d2015-10-07 19:25:333666 new HttpAuthHandlerMock::Factory());
3667 auth_handler_factory->set_do_init_from_challenge(true);
danakj1fd259a02016-04-16 03:17:093668 std::unique_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
mmenke2a1781d2015-10-07 19:25:333669 mock_handler->set_allows_default_credentials(true);
3670 auth_handler_factory->AddMockHandler(mock_handler.release(),
3671 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483672 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333673
3674 // Add NetLog just so can verify load timing information gets a NetLog ID.
3675 NetLog net_log;
3676 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:093677 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333678
3679 // Since we have proxy, should try to establish tunnel.
3680 MockWrite data_writes1[] = {
3681 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173682 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333683 "Proxy-Connection: keep-alive\r\n\r\n"),
3684 };
3685
3686 // The proxy responds to the connect with a 407, using a non-persistent
3687 // connection.
3688 MockRead data_reads1[] = {
3689 // No credentials.
3690 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3691 MockRead("Proxy-Authenticate: Mock\r\n"),
3692 MockRead("Proxy-Connection: close\r\n\r\n"),
3693 };
3694
3695 // Since the first connection couldn't be reused, need to establish another
3696 // once given credentials.
3697 MockWrite data_writes2[] = {
3698 // After calling trans->RestartWithAuth(), this is the request we should
3699 // be issuing -- the final header line contains the credentials.
3700 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173701 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333702 "Proxy-Connection: keep-alive\r\n"
3703 "Proxy-Authorization: auth_token\r\n\r\n"),
3704
3705 MockWrite("GET / HTTP/1.1\r\n"
3706 "Host: www.example.org\r\n"
3707 "Connection: keep-alive\r\n\r\n"),
3708 };
3709
3710 MockRead data_reads2[] = {
3711 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3712
3713 MockRead("HTTP/1.1 200 OK\r\n"),
3714 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3715 MockRead("Content-Length: 5\r\n\r\n"),
3716 MockRead(SYNCHRONOUS, "hello"),
3717 };
3718
3719 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3720 data_writes1, arraysize(data_writes1));
3721 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3722 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3723 data_writes2, arraysize(data_writes2));
3724 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3725 SSLSocketDataProvider ssl(ASYNC, OK);
3726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3727
danakj1fd259a02016-04-16 03:17:093728 std::unique_ptr<HttpTransaction> trans(
mmenke2a1781d2015-10-07 19:25:333729 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3730
3731 TestCompletionCallback callback;
3732 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013733 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:333734
3735 const HttpResponseInfo* response = trans->GetResponseInfo();
3736 ASSERT_TRUE(response);
3737 ASSERT_TRUE(response->headers);
3738 EXPECT_FALSE(response->headers->IsKeepAlive());
3739 EXPECT_EQ(407, response->headers->response_code());
3740 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3741 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
wezca1070932016-05-26 20:30:523742 EXPECT_FALSE(response->auth_challenge);
mmenke2a1781d2015-10-07 19:25:333743
3744 LoadTimingInfo load_timing_info;
3745 // CONNECT requests and responses are handled at the connect job level, so
3746 // the transaction does not yet have a connection.
3747 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3748
3749 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:013750 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:333751 response = trans->GetResponseInfo();
3752 ASSERT_TRUE(response);
3753 ASSERT_TRUE(response->headers);
3754 EXPECT_TRUE(response->headers->IsKeepAlive());
3755 EXPECT_EQ(200, response->headers->response_code());
3756 EXPECT_EQ(5, response->headers->GetContentLength());
3757 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3758
3759 // The password prompt info should not be set.
3760 EXPECT_FALSE(response->auth_challenge);
3761
3762 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3763 TestLoadTimingNotReusedWithPac(load_timing_info,
3764 CONNECT_TIMING_HAS_SSL_TIMES);
3765
3766 trans.reset();
3767 session->CloseAllConnections();
3768}
3769
3770// Test a proxy auth scheme that allows default credentials and a proxy server
3771// that hangs up when credentials are initially sent.
bncd16676a2016-07-20 16:23:013772TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:333773 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
3774 HttpRequestInfo request;
3775 request.method = "GET";
3776 request.url = GURL("https://www.example.org/");
3777
3778 // Configure against proxy server "myproxy:70".
3779 session_deps_.proxy_service =
3780 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3781
danakj1fd259a02016-04-16 03:17:093782 std::unique_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
mmenke2a1781d2015-10-07 19:25:333783 new HttpAuthHandlerMock::Factory());
3784 auth_handler_factory->set_do_init_from_challenge(true);
danakj1fd259a02016-04-16 03:17:093785 std::unique_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
mmenke2a1781d2015-10-07 19:25:333786 mock_handler->set_allows_default_credentials(true);
3787 auth_handler_factory->AddMockHandler(mock_handler.release(),
3788 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483789 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333790
3791 // Add NetLog just so can verify load timing information gets a NetLog ID.
3792 NetLog net_log;
3793 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:093794 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333795
3796 // Should try to establish tunnel.
3797 MockWrite data_writes1[] = {
3798 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173799 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333800 "Proxy-Connection: keep-alive\r\n\r\n"),
3801
3802 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173803 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333804 "Proxy-Connection: keep-alive\r\n"
3805 "Proxy-Authorization: auth_token\r\n\r\n"),
3806 };
3807
3808 // The proxy responds to the connect with a 407, using a non-persistent
3809 // connection.
3810 MockRead data_reads1[] = {
3811 // No credentials.
3812 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3813 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3814 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3815 };
3816
3817 // Since the first connection was closed, need to establish another once given
3818 // credentials.
3819 MockWrite data_writes2[] = {
3820 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173821 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333822 "Proxy-Connection: keep-alive\r\n"
3823 "Proxy-Authorization: auth_token\r\n\r\n"),
3824
3825 MockWrite("GET / HTTP/1.1\r\n"
3826 "Host: www.example.org\r\n"
3827 "Connection: keep-alive\r\n\r\n"),
3828 };
3829
3830 MockRead data_reads2[] = {
3831 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3832
3833 MockRead("HTTP/1.1 200 OK\r\n"),
3834 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3835 MockRead("Content-Length: 5\r\n\r\n"),
3836 MockRead(SYNCHRONOUS, "hello"),
3837 };
3838
3839 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3840 data_writes1, arraysize(data_writes1));
3841 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3842 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3843 data_writes2, arraysize(data_writes2));
3844 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3845 SSLSocketDataProvider ssl(ASYNC, OK);
3846 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3847
danakj1fd259a02016-04-16 03:17:093848 std::unique_ptr<HttpTransaction> trans(
mmenke2a1781d2015-10-07 19:25:333849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3850
3851 TestCompletionCallback callback;
3852 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013853 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:333854
3855 const HttpResponseInfo* response = trans->GetResponseInfo();
3856 ASSERT_TRUE(response);
3857 ASSERT_TRUE(response->headers);
3858 EXPECT_TRUE(response->headers->IsKeepAlive());
3859 EXPECT_EQ(407, response->headers->response_code());
3860 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3861 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3862 EXPECT_FALSE(response->auth_challenge);
3863
3864 LoadTimingInfo load_timing_info;
3865 // CONNECT requests and responses are handled at the connect job level, so
3866 // the transaction does not yet have a connection.
3867 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3868
3869 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:013870 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:333871
3872 response = trans->GetResponseInfo();
3873 ASSERT_TRUE(response);
3874 ASSERT_TRUE(response->headers);
3875 EXPECT_TRUE(response->headers->IsKeepAlive());
3876 EXPECT_EQ(200, response->headers->response_code());
3877 EXPECT_EQ(5, response->headers->GetContentLength());
3878 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3879
3880 // The password prompt info should not be set.
wezca1070932016-05-26 20:30:523881 EXPECT_FALSE(response->auth_challenge);
mmenke2a1781d2015-10-07 19:25:333882
3883 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3884 TestLoadTimingNotReusedWithPac(load_timing_info,
3885 CONNECT_TIMING_HAS_SSL_TIMES);
3886
3887 trans.reset();
3888 session->CloseAllConnections();
3889}
3890
3891// Test a proxy auth scheme that allows default credentials and a proxy server
3892// that hangs up when credentials are initially sent, and hangs up again when
3893// they are retried.
bncd16676a2016-07-20 16:23:013894TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:333895 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
3896 HttpRequestInfo request;
3897 request.method = "GET";
3898 request.url = GURL("https://www.example.org/");
3899
3900 // Configure against proxy server "myproxy:70".
3901 session_deps_.proxy_service =
3902 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
3903
danakj1fd259a02016-04-16 03:17:093904 std::unique_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
mmenke2a1781d2015-10-07 19:25:333905 new HttpAuthHandlerMock::Factory());
3906 auth_handler_factory->set_do_init_from_challenge(true);
danakj1fd259a02016-04-16 03:17:093907 std::unique_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
mmenke2a1781d2015-10-07 19:25:333908 mock_handler->set_allows_default_credentials(true);
3909 auth_handler_factory->AddMockHandler(mock_handler.release(),
3910 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:483911 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:333912
3913 // Add NetLog just so can verify load timing information gets a NetLog ID.
3914 NetLog net_log;
3915 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:093916 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:333917
3918 // Should try to establish tunnel.
3919 MockWrite data_writes1[] = {
3920 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173921 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333922 "Proxy-Connection: keep-alive\r\n\r\n"),
3923
3924 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173925 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333926 "Proxy-Connection: keep-alive\r\n"
3927 "Proxy-Authorization: auth_token\r\n\r\n"),
3928 };
3929
3930 // The proxy responds to the connect with a 407, and then hangs up after the
3931 // second request is sent.
3932 MockRead data_reads1[] = {
3933 // No credentials.
3934 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3935 MockRead("Content-Length: 0\r\n"),
3936 MockRead("Proxy-Connection: keep-alive\r\n"),
3937 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
3938 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3939 };
3940
3941 // HttpNetworkTransaction sees a reused connection that was closed with
3942 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
3943 // request.
3944 MockWrite data_writes2[] = {
3945 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:173946 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:333947 "Proxy-Connection: keep-alive\r\n\r\n"),
3948 };
3949
3950 // The proxy, having had more than enough of us, just hangs up.
3951 MockRead data_reads2[] = {
3952 // No credentials.
3953 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
3954 };
3955
3956 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3957 data_writes1, arraysize(data_writes1));
3958 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3959 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3960 data_writes2, arraysize(data_writes2));
3961 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3962
danakj1fd259a02016-04-16 03:17:093963 std::unique_ptr<HttpTransaction> trans(
mmenke2a1781d2015-10-07 19:25:333964 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3965
3966 TestCompletionCallback callback;
3967 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:013968 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:333969
3970 const HttpResponseInfo* response = trans->GetResponseInfo();
3971 ASSERT_TRUE(response);
3972 ASSERT_TRUE(response->headers);
3973 EXPECT_TRUE(response->headers->IsKeepAlive());
3974 EXPECT_EQ(407, response->headers->response_code());
3975 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3976 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3977 EXPECT_FALSE(response->auth_challenge);
3978
3979 LoadTimingInfo load_timing_info;
3980 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3981
3982 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:013983 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
mmenke2a1781d2015-10-07 19:25:333984
3985 trans.reset();
3986 session->CloseAllConnections();
3987}
3988
3989// Test a proxy auth scheme that allows default credentials and a proxy server
3990// that hangs up when credentials are initially sent, and sends a challenge
3991// again they are retried.
bncd16676a2016-07-20 16:23:013992TEST_F(HttpNetworkTransactionTest,
mmenke2a1781d2015-10-07 19:25:333993 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
3994 HttpRequestInfo request;
3995 request.method = "GET";
3996 request.url = GURL("https://www.example.org/");
3997
3998 // Configure against proxy server "myproxy:70".
3999 session_deps_.proxy_service =
4000 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
4001
danakj1fd259a02016-04-16 03:17:094002 std::unique_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory(
mmenke2a1781d2015-10-07 19:25:334003 new HttpAuthHandlerMock::Factory());
4004 auth_handler_factory->set_do_init_from_challenge(true);
danakj1fd259a02016-04-16 03:17:094005 std::unique_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock());
mmenke2a1781d2015-10-07 19:25:334006 mock_handler->set_allows_default_credentials(true);
4007 auth_handler_factory->AddMockHandler(mock_handler.release(),
4008 HttpAuth::AUTH_PROXY);
4009 // Add another handler for the second challenge. It supports default
4010 // credentials, but they shouldn't be used, since they were already tried.
4011 mock_handler.reset(new HttpAuthHandlerMock());
4012 mock_handler->set_allows_default_credentials(true);
4013 auth_handler_factory->AddMockHandler(mock_handler.release(),
4014 HttpAuth::AUTH_PROXY);
dchengc7eeda422015-12-26 03:56:484015 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
mmenke2a1781d2015-10-07 19:25:334016
4017 // Add NetLog just so can verify load timing information gets a NetLog ID.
4018 NetLog net_log;
4019 session_deps_.net_log = &net_log;
danakj1fd259a02016-04-16 03:17:094020 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
mmenke2a1781d2015-10-07 19:25:334021
4022 // Should try to establish tunnel.
4023 MockWrite data_writes1[] = {
4024 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174025 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334026 "Proxy-Connection: keep-alive\r\n\r\n"),
4027 };
4028
4029 // The proxy responds to the connect with a 407, using a non-persistent
4030 // connection.
4031 MockRead data_reads1[] = {
4032 // No credentials.
4033 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4034 MockRead("Proxy-Authenticate: Mock\r\n"),
4035 MockRead("Proxy-Connection: close\r\n\r\n"),
4036 };
4037
4038 // Since the first connection was closed, need to establish another once given
4039 // credentials.
4040 MockWrite data_writes2[] = {
4041 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:174042 "Host: www.example.org:443\r\n"
mmenke2a1781d2015-10-07 19:25:334043 "Proxy-Connection: keep-alive\r\n"
4044 "Proxy-Authorization: auth_token\r\n\r\n"),
4045 };
4046
4047 MockRead data_reads2[] = {
4048 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4049 MockRead("Proxy-Authenticate: Mock\r\n"),
4050 MockRead("Proxy-Connection: close\r\n\r\n"),
4051 };
4052
4053 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4054 data_writes1, arraysize(data_writes1));
4055 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4056 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4057 data_writes2, arraysize(data_writes2));
4058 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4059 SSLSocketDataProvider ssl(ASYNC, OK);
4060 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4061
danakj1fd259a02016-04-16 03:17:094062 std::unique_ptr<HttpTransaction> trans(
mmenke2a1781d2015-10-07 19:25:334063 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4064
4065 TestCompletionCallback callback;
4066 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014067 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334068
4069 const HttpResponseInfo* response = trans->GetResponseInfo();
4070 ASSERT_TRUE(response);
4071 ASSERT_TRUE(response->headers);
4072 EXPECT_EQ(407, response->headers->response_code());
4073 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4074 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4075 EXPECT_FALSE(response->auth_challenge);
4076
4077 LoadTimingInfo load_timing_info;
4078 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4079
4080 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
robpercival214763f2016-07-01 23:27:014081 EXPECT_THAT(callback.GetResult(rv), IsOk());
mmenke2a1781d2015-10-07 19:25:334082 response = trans->GetResponseInfo();
4083 ASSERT_TRUE(response);
4084 ASSERT_TRUE(response->headers);
4085 EXPECT_EQ(407, response->headers->response_code());
4086 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4087 EXPECT_TRUE(response->auth_challenge);
4088
4089 trans.reset();
4090 session->CloseAllConnections();
4091}
4092
[email protected]029c83b62013-01-24 05:28:204093// Test the load timing for HTTPS requests with an HTTP proxy.
bncd16676a2016-07-20 16:23:014094TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:204095 HttpRequestInfo request1;
4096 request1.method = "GET";
bncce36dca22015-04-21 22:11:234097 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:204098
4099 HttpRequestInfo request2;
4100 request2.method = "GET";
bncce36dca22015-04-21 22:11:234101 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:204102
4103 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034104 session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:514105 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074106 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094107 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:204108
4109 // Since we have proxy, should try to establish tunnel.
4110 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174111 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4112 "Host: www.example.org:443\r\n"
4113 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204114
rsleevidb16bb02015-11-12 23:47:174115 MockWrite("GET /1 HTTP/1.1\r\n"
4116 "Host: www.example.org\r\n"
4117 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204118
rsleevidb16bb02015-11-12 23:47:174119 MockWrite("GET /2 HTTP/1.1\r\n"
4120 "Host: www.example.org\r\n"
4121 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204122 };
4123
4124 // The proxy responds to the connect with a 407, using a persistent
4125 // connection.
4126 MockRead data_reads1[] = {
4127 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4128
4129 MockRead("HTTP/1.1 200 OK\r\n"),
4130 MockRead("Content-Length: 1\r\n\r\n"),
4131 MockRead(SYNCHRONOUS, "1"),
4132
4133 MockRead("HTTP/1.1 200 OK\r\n"),
4134 MockRead("Content-Length: 2\r\n\r\n"),
4135 MockRead(SYNCHRONOUS, "22"),
4136 };
4137
4138 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4139 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074140 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:204141 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074142 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:204143
4144 TestCompletionCallback callback1;
danakj1fd259a02016-04-16 03:17:094145 std::unique_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:504146 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204147
4148 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014149 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:204150
4151 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014152 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:204153
4154 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:524155 ASSERT_TRUE(response1);
4156 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:204157 EXPECT_EQ(1, response1->headers->GetContentLength());
4158
4159 LoadTimingInfo load_timing_info1;
4160 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4161 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
4162
4163 trans1.reset();
4164
4165 TestCompletionCallback callback2;
danakj1fd259a02016-04-16 03:17:094166 std::unique_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504167 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204168
4169 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014170 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:204171
4172 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:014173 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:204174
4175 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:524176 ASSERT_TRUE(response2);
4177 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:204178 EXPECT_EQ(2, response2->headers->GetContentLength());
4179
4180 LoadTimingInfo load_timing_info2;
4181 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4182 TestLoadTimingReused(load_timing_info2);
4183
4184 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4185
4186 trans2.reset();
4187 session->CloseAllConnections();
4188}
4189
4190// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
bncd16676a2016-07-20 16:23:014191TEST_F(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
[email protected]029c83b62013-01-24 05:28:204192 HttpRequestInfo request1;
4193 request1.method = "GET";
bncce36dca22015-04-21 22:11:234194 request1.url = GURL("https://www.example.org/1");
[email protected]029c83b62013-01-24 05:28:204195
4196 HttpRequestInfo request2;
4197 request2.method = "GET";
bncce36dca22015-04-21 22:11:234198 request2.url = GURL("https://www.example.org/2");
[email protected]029c83b62013-01-24 05:28:204199
4200 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034201 session_deps_.proxy_service =
4202 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:514203 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074204 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094205 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]029c83b62013-01-24 05:28:204206
4207 // Since we have proxy, should try to establish tunnel.
4208 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:174209 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4210 "Host: www.example.org:443\r\n"
4211 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204212
rsleevidb16bb02015-11-12 23:47:174213 MockWrite("GET /1 HTTP/1.1\r\n"
4214 "Host: www.example.org\r\n"
4215 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204216
rsleevidb16bb02015-11-12 23:47:174217 MockWrite("GET /2 HTTP/1.1\r\n"
4218 "Host: www.example.org\r\n"
4219 "Connection: keep-alive\r\n\r\n"),
[email protected]029c83b62013-01-24 05:28:204220 };
4221
4222 // The proxy responds to the connect with a 407, using a persistent
4223 // connection.
4224 MockRead data_reads1[] = {
4225 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4226
4227 MockRead("HTTP/1.1 200 OK\r\n"),
4228 MockRead("Content-Length: 1\r\n\r\n"),
4229 MockRead(SYNCHRONOUS, "1"),
4230
4231 MockRead("HTTP/1.1 200 OK\r\n"),
4232 MockRead("Content-Length: 2\r\n\r\n"),
4233 MockRead(SYNCHRONOUS, "22"),
4234 };
4235
4236 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4237 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074238 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]029c83b62013-01-24 05:28:204239 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]029c83b62013-01-24 05:28:204241
4242 TestCompletionCallback callback1;
danakj1fd259a02016-04-16 03:17:094243 std::unique_ptr<HttpTransaction> trans1(
[email protected]90499482013-06-01 00:39:504244 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204245
4246 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014247 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:204248
4249 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014250 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:204251
4252 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:524253 ASSERT_TRUE(response1);
4254 ASSERT_TRUE(response1->headers);
[email protected]029c83b62013-01-24 05:28:204255 EXPECT_EQ(1, response1->headers->GetContentLength());
4256
4257 LoadTimingInfo load_timing_info1;
4258 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
4259 TestLoadTimingNotReusedWithPac(load_timing_info1,
4260 CONNECT_TIMING_HAS_SSL_TIMES);
4261
4262 trans1.reset();
4263
4264 TestCompletionCallback callback2;
danakj1fd259a02016-04-16 03:17:094265 std::unique_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504266 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:204267
4268 rv = trans2->Start(&request2, callback2.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014269 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:204270
4271 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:014272 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:204273
4274 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:524275 ASSERT_TRUE(response2);
4276 ASSERT_TRUE(response2->headers);
[email protected]029c83b62013-01-24 05:28:204277 EXPECT_EQ(2, response2->headers->GetContentLength());
4278
4279 LoadTimingInfo load_timing_info2;
4280 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4281 TestLoadTimingReusedWithPac(load_timing_info2);
4282
4283 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
4284
4285 trans2.reset();
4286 session->CloseAllConnections();
4287}
4288
[email protected]2df19bb2010-08-25 20:13:464289// Test a simple get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:014290TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274291 HttpRequestInfo request;
4292 request.method = "GET";
bncce36dca22015-04-21 22:11:234293 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274294
[email protected]2df19bb2010-08-25 20:13:464295 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034296 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514297 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074298 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094299 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2df19bb2010-08-25 20:13:464300
[email protected]2df19bb2010-08-25 20:13:464301 // Since we have proxy, should use full url
4302 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:234303 MockWrite(
4304 "GET http://www.example.org/ HTTP/1.1\r\n"
4305 "Host: www.example.org\r\n"
4306 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:464307 };
4308
4309 MockRead data_reads1[] = {
4310 MockRead("HTTP/1.1 200 OK\r\n"),
4311 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4312 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064313 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464314 };
4315
4316 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4317 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:074318 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:064319 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074320 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:464321
[email protected]49639fa2011-12-20 23:22:414322 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:464323
danakj1fd259a02016-04-16 03:17:094324 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504325 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504326
[email protected]49639fa2011-12-20 23:22:414327 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014328 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:464329
4330 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014331 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:464332
[email protected]58e32bb2013-01-21 18:23:254333 LoadTimingInfo load_timing_info;
4334 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4335 TestLoadTimingNotReused(load_timing_info,
4336 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4337
[email protected]2df19bb2010-08-25 20:13:464338 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524339 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:464340
4341 EXPECT_TRUE(response->headers->IsKeepAlive());
4342 EXPECT_EQ(200, response->headers->response_code());
4343 EXPECT_EQ(100, response->headers->GetContentLength());
4344 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4345
4346 // The password prompt info should not be set.
wezca1070932016-05-26 20:30:524347 EXPECT_FALSE(response->auth_challenge);
[email protected]2df19bb2010-08-25 20:13:464348}
4349
[email protected]7642b5ae2010-09-01 20:55:174350// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:014351TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:274352 HttpRequestInfo request;
4353 request.method = "GET";
bncce36dca22015-04-21 22:11:234354 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274355 request.load_flags = 0;
4356
[email protected]7642b5ae2010-09-01 20:55:174357 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034358 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514359 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074360 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094361 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7642b5ae2010-09-01 20:55:174362
bncce36dca22015-04-21 22:11:234363 // fetch http://www.example.org/ via SPDY
bncdf80d44fd2016-07-15 20:27:414364 SpdySerializedFrame req(
bncb26024382016-06-29 02:39:454365 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414366 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]7642b5ae2010-09-01 20:55:174367
bnc42331402016-07-25 13:36:154368 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:414369 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7642b5ae2010-09-01 20:55:174370 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414371 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]7642b5ae2010-09-01 20:55:174372 };
4373
rch8e6c6c42015-05-01 14:05:134374 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4375 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074376 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7642b5ae2010-09-01 20:55:174377
[email protected]8ddf8322012-02-23 18:08:064378 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364379 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:074380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]7642b5ae2010-09-01 20:55:174381
[email protected]49639fa2011-12-20 23:22:414382 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:174383
danakj1fd259a02016-04-16 03:17:094384 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504385 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:504386
[email protected]49639fa2011-12-20 23:22:414387 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014388 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7642b5ae2010-09-01 20:55:174389
4390 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014391 EXPECT_THAT(rv, IsOk());
[email protected]7642b5ae2010-09-01 20:55:174392
[email protected]58e32bb2013-01-21 18:23:254393 LoadTimingInfo load_timing_info;
4394 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4395 TestLoadTimingNotReused(load_timing_info,
4396 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
4397
[email protected]7642b5ae2010-09-01 20:55:174398 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524399 ASSERT_TRUE(response);
4400 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:024401 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]7642b5ae2010-09-01 20:55:174402
4403 std::string response_data;
robpercival214763f2016-07-01 23:27:014404 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:234405 EXPECT_EQ(kUploadData, response_data);
[email protected]7642b5ae2010-09-01 20:55:174406}
4407
[email protected]1c173852014-06-19 12:51:504408// Verifies that a session which races and wins against the owning transaction
4409// (completing prior to host resolution), doesn't fail the transaction.
4410// Regression test for crbug.com/334413.
bncd16676a2016-07-20 16:23:014411TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
[email protected]1c173852014-06-19 12:51:504412 HttpRequestInfo request;
4413 request.method = "GET";
bncce36dca22015-04-21 22:11:234414 request.url = GURL("http://www.example.org/");
[email protected]1c173852014-06-19 12:51:504415 request.load_flags = 0;
4416
4417 // Configure SPDY proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034418 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514419 BoundTestNetLog log;
[email protected]1c173852014-06-19 12:51:504420 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094421 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]1c173852014-06-19 12:51:504422
bncce36dca22015-04-21 22:11:234423 // Fetch http://www.example.org/ through the SPDY proxy.
bncdf80d44fd2016-07-15 20:27:414424 SpdySerializedFrame req(
bncb26024382016-06-29 02:39:454425 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414426 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]1c173852014-06-19 12:51:504427
bnc42331402016-07-25 13:36:154428 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414429 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]1c173852014-06-19 12:51:504430 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414431 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]1c173852014-06-19 12:51:504432 };
4433
rch8e6c6c42015-05-01 14:05:134434 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4435 arraysize(spdy_writes));
[email protected]1c173852014-06-19 12:51:504436 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
4437
4438 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364439 ssl.next_proto = kProtoHTTP2;
[email protected]1c173852014-06-19 12:51:504440 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4441
4442 TestCompletionCallback callback1;
4443
danakj1fd259a02016-04-16 03:17:094444 std::unique_ptr<HttpTransaction> trans(
[email protected]1c173852014-06-19 12:51:504445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4446
4447 // Stall the hostname resolution begun by the transaction.
4448 session_deps_.host_resolver->set_synchronous_mode(false);
4449 session_deps_.host_resolver->set_ondemand_mode(true);
4450
4451 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014452 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c173852014-06-19 12:51:504453
4454 // Race a session to the proxy, which completes first.
4455 session_deps_.host_resolver->set_ondemand_mode(false);
4456 SpdySessionKey key(
4457 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4458 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:424459 CreateSecureSpdySession(session.get(), key, log.bound());
[email protected]1c173852014-06-19 12:51:504460
4461 // Unstall the resolution begun by the transaction.
4462 session_deps_.host_resolver->set_ondemand_mode(true);
4463 session_deps_.host_resolver->ResolveAllPending();
4464
4465 EXPECT_FALSE(callback1.have_result());
4466 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014467 EXPECT_THAT(rv, IsOk());
[email protected]1c173852014-06-19 12:51:504468
4469 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524470 ASSERT_TRUE(response);
4471 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:024472 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]1c173852014-06-19 12:51:504473
4474 std::string response_data;
robpercival214763f2016-07-01 23:27:014475 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]1c173852014-06-19 12:51:504476 EXPECT_EQ(kUploadData, response_data);
4477}
4478
[email protected]dc7bd1c52010-11-12 00:01:134479// Test a SPDY get through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:014480TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:274481 HttpRequestInfo request;
4482 request.method = "GET";
bncce36dca22015-04-21 22:11:234483 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274484 request.load_flags = 0;
4485
[email protected]79cb5c12011-09-12 13:12:044486 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:034487 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:514488 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074489 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094490 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]dc7bd1c52010-11-12 00:01:134491
[email protected]dc7bd1c52010-11-12 00:01:134492 // The first request will be a bare GET, the second request will be a
4493 // GET with a Proxy-Authorization header.
bncb26024382016-06-29 02:39:454494 spdy_util_.set_default_url(request.url);
bncdf80d44fd2016-07-15 20:27:414495 SpdySerializedFrame req_get(
bnc38dcd392016-02-09 23:19:494496 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, false));
rdsmithebb50aa2015-11-12 03:44:384497 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]dc7bd1c52010-11-12 00:01:134498 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464499 "proxy-authorization", "Basic Zm9vOmJhcg=="
[email protected]dc7bd1c52010-11-12 00:01:134500 };
bncdf80d44fd2016-07-15 20:27:414501 SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
4502 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders) / 2, 3,
4503 LOWEST, false));
[email protected]dc7bd1c52010-11-12 00:01:134504 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414505 CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3),
[email protected]dc7bd1c52010-11-12 00:01:134506 };
4507
4508 // The first response is a 407 proxy authentication challenge, and the second
4509 // response will be a 200 response since the second request includes a valid
4510 // Authorization header.
4511 const char* const kExtraAuthenticationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464512 "proxy-authenticate", "Basic realm=\"MyRealm1\""
[email protected]dc7bd1c52010-11-12 00:01:134513 };
bnc42331402016-07-25 13:36:154514 SpdySerializedFrame resp_authentication(spdy_util_.ConstructSpdyReplyError(
bncdf80d44fd2016-07-15 20:27:414515 "407 Proxy Authentication Required", kExtraAuthenticationHeaders,
4516 arraysize(kExtraAuthenticationHeaders) / 2, 1));
4517 SpdySerializedFrame body_authentication(
4518 spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:154519 SpdySerializedFrame resp_data(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:414520 SpdySerializedFrame body_data(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]dc7bd1c52010-11-12 00:01:134521 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414522 CreateMockRead(resp_authentication, 1),
4523 CreateMockRead(body_authentication, 2),
4524 CreateMockRead(resp_data, 4),
4525 CreateMockRead(body_data, 5),
rch8e6c6c42015-05-01 14:05:134526 MockRead(ASYNC, 0, 6),
[email protected]dc7bd1c52010-11-12 00:01:134527 };
4528
rch8e6c6c42015-05-01 14:05:134529 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4530 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074531 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]dc7bd1c52010-11-12 00:01:134532
[email protected]8ddf8322012-02-23 18:08:064533 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364534 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:074535 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]dc7bd1c52010-11-12 00:01:134536
[email protected]49639fa2011-12-20 23:22:414537 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:134538
danakj1fd259a02016-04-16 03:17:094539 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504540 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]dc7bd1c52010-11-12 00:01:134541
[email protected]49639fa2011-12-20 23:22:414542 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014543 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:134544
4545 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014546 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:134547
4548 const HttpResponseInfo* const response = trans->GetResponseInfo();
4549
wezca1070932016-05-26 20:30:524550 ASSERT_TRUE(response);
4551 ASSERT_TRUE(response->headers);
[email protected]dc7bd1c52010-11-12 00:01:134552 EXPECT_EQ(407, response->headers->response_code());
4553 EXPECT_TRUE(response->was_fetched_via_spdy);
asanka098c0092016-06-16 20:18:434554 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:134555
[email protected]49639fa2011-12-20 23:22:414556 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:134557
[email protected]49639fa2011-12-20 23:22:414558 rv = trans->RestartWithAuth(
4559 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:014560 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]dc7bd1c52010-11-12 00:01:134561
4562 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:014563 EXPECT_THAT(rv, IsOk());
[email protected]dc7bd1c52010-11-12 00:01:134564
4565 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4566
wezca1070932016-05-26 20:30:524567 ASSERT_TRUE(response_restart);
4568 ASSERT_TRUE(response_restart->headers);
[email protected]dc7bd1c52010-11-12 00:01:134569 EXPECT_EQ(200, response_restart->headers->response_code());
4570 // The password prompt info should not be set.
wezca1070932016-05-26 20:30:524571 EXPECT_FALSE(response_restart->auth_challenge);
[email protected]dc7bd1c52010-11-12 00:01:134572}
4573
[email protected]d9da5fe2010-10-13 22:37:164574// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
bncd16676a2016-07-20 16:23:014575TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:274576 HttpRequestInfo request;
4577 request.method = "GET";
bncce36dca22015-04-21 22:11:234578 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274579 request.load_flags = 0;
4580
[email protected]d9da5fe2010-10-13 22:37:164581 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034582 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514583 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074584 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094585 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164586
danakj1fd259a02016-04-16 03:17:094587 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504588 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164589
bncce36dca22015-04-21 22:11:234590 // CONNECT to www.example.org:443 via SPDY
bncdf80d44fd2016-07-15 20:27:414591 SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234592 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4593 // fetch https://www.example.org/ via HTTP
[email protected]d9da5fe2010-10-13 22:37:164594
bncce36dca22015-04-21 22:11:234595 const char get[] =
4596 "GET / HTTP/1.1\r\n"
4597 "Host: www.example.org\r\n"
4598 "Connection: keep-alive\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414599 SpdySerializedFrame wrapped_get(
4600 spdy_util_.ConstructSpdyDataFrame(1, get, strlen(get), false));
bnc42331402016-07-25 13:36:154601 SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]d9da5fe2010-10-13 22:37:164602 const char resp[] = "HTTP/1.1 200 OK\r\n"
4603 "Content-Length: 10\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414604 SpdySerializedFrame wrapped_get_resp(
4605 spdy_util_.ConstructSpdyDataFrame(1, resp, strlen(resp), false));
4606 SpdySerializedFrame wrapped_body(
4607 spdy_util_.ConstructSpdyDataFrame(1, "1234567890", 10, false));
4608 SpdySerializedFrame window_update(
4609 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
[email protected]8d2f7012012-02-16 00:08:044610
4611 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414612 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
4613 CreateMockWrite(window_update, 6),
[email protected]8d2f7012012-02-16 00:08:044614 };
4615
[email protected]d9da5fe2010-10-13 22:37:164616 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414617 CreateMockRead(conn_resp, 1, ASYNC),
4618 CreateMockRead(wrapped_get_resp, 3, ASYNC),
4619 CreateMockRead(wrapped_body, 4, ASYNC),
4620 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:134621 MockRead(ASYNC, 0, 7),
[email protected]d9da5fe2010-10-13 22:37:164622 };
4623
rch8e6c6c42015-05-01 14:05:134624 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4625 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074626 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164627
[email protected]8ddf8322012-02-23 18:08:064628 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364629 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:074630 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064631 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:074632 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164633
[email protected]49639fa2011-12-20 23:22:414634 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164635
[email protected]49639fa2011-12-20 23:22:414636 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014637 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:164638
4639 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014640 ASSERT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:164641
[email protected]58e32bb2013-01-21 18:23:254642 LoadTimingInfo load_timing_info;
4643 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4644 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4645
[email protected]d9da5fe2010-10-13 22:37:164646 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524647 ASSERT_TRUE(response);
4648 ASSERT_TRUE(response->headers);
[email protected]d9da5fe2010-10-13 22:37:164649 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4650
4651 std::string response_data;
robpercival214763f2016-07-01 23:27:014652 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]d9da5fe2010-10-13 22:37:164653 EXPECT_EQ("1234567890", response_data);
4654}
4655
4656// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
bncd16676a2016-07-20 16:23:014657TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
4658 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:384659
[email protected]cb9bf6ca2011-01-28 13:15:274660 HttpRequestInfo request;
4661 request.method = "GET";
bncce36dca22015-04-21 22:11:234662 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274663 request.load_flags = 0;
4664
[email protected]d9da5fe2010-10-13 22:37:164665 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034666 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514667 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074668 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094669 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164670
danakj1fd259a02016-04-16 03:17:094671 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504672 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164673
bncce36dca22015-04-21 22:11:234674 // CONNECT to www.example.org:443 via SPDY
bncdf80d44fd2016-07-15 20:27:414675 SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234676 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
4677 // fetch https://www.example.org/ via SPDY
4678 const char kMyUrl[] = "https://www.example.org/";
bncdf80d44fd2016-07-15 20:27:414679 SpdySerializedFrame get(
bnc38dcd392016-02-09 23:19:494680 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:414681 SpdySerializedFrame wrapped_get(spdy_util_.ConstructWrappedSpdyFrame(get, 1));
bnc42331402016-07-25 13:36:154682 SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414683 SpdySerializedFrame get_resp(
bnc42331402016-07-25 13:36:154684 spdy_util_wrapped.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:414685 SpdySerializedFrame wrapped_get_resp(
[email protected]23e482282013-06-14 16:08:024686 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
bncdf80d44fd2016-07-15 20:27:414687 SpdySerializedFrame body(spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
4688 SpdySerializedFrame wrapped_body(
[email protected]23e482282013-06-14 16:08:024689 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
bncdf80d44fd2016-07-15 20:27:414690 SpdySerializedFrame window_update_get_resp(
4691 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
4692 SpdySerializedFrame window_update_body(
4693 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
[email protected]8d2f7012012-02-16 00:08:044694
4695 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414696 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_get, 2),
4697 CreateMockWrite(window_update_get_resp, 6),
4698 CreateMockWrite(window_update_body, 7),
[email protected]8d2f7012012-02-16 00:08:044699 };
4700
[email protected]d9da5fe2010-10-13 22:37:164701 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414702 CreateMockRead(conn_resp, 1, ASYNC),
rch32320842015-05-16 15:57:094703 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:414704 CreateMockRead(wrapped_get_resp, 4, ASYNC),
4705 CreateMockRead(wrapped_body, 5, ASYNC),
rch8e6c6c42015-05-01 14:05:134706 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:164707 };
4708
rch32320842015-05-16 15:57:094709 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4710 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074711 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164712
[email protected]8ddf8322012-02-23 18:08:064713 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364714 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:074715 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064716 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364717 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:074718 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164719
[email protected]49639fa2011-12-20 23:22:414720 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164721
[email protected]49639fa2011-12-20 23:22:414722 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014723 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:164724
rch32320842015-05-16 15:57:094725 // Allow the SpdyProxyClientSocket's write callback to complete.
fdoray92e35a72016-06-10 15:54:554726 base::RunLoop().RunUntilIdle();
rch32320842015-05-16 15:57:094727 // Now allow the read of the response to complete.
mmenkee24011922015-12-17 22:12:594728 spdy_data.Resume();
[email protected]d9da5fe2010-10-13 22:37:164729 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014730 EXPECT_THAT(rv, IsOk());
[email protected]d9da5fe2010-10-13 22:37:164731
[email protected]58e32bb2013-01-21 18:23:254732 LoadTimingInfo load_timing_info;
4733 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4734 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4735
[email protected]d9da5fe2010-10-13 22:37:164736 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524737 ASSERT_TRUE(response);
4738 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:024739 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d9da5fe2010-10-13 22:37:164740
4741 std::string response_data;
robpercival214763f2016-07-01 23:27:014742 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]448d4ca52012-03-04 04:12:234743 EXPECT_EQ(kUploadData, response_data);
[email protected]d9da5fe2010-10-13 22:37:164744}
4745
4746// Test a SPDY CONNECT failure through an HTTPS Proxy.
bncd16676a2016-07-20 16:23:014747TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:274748 HttpRequestInfo request;
4749 request.method = "GET";
bncce36dca22015-04-21 22:11:234750 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:274751 request.load_flags = 0;
4752
[email protected]d9da5fe2010-10-13 22:37:164753 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034754 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514755 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074756 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094757 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d9da5fe2010-10-13 22:37:164758
danakj1fd259a02016-04-16 03:17:094759 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504760 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]d9da5fe2010-10-13 22:37:164761
bncce36dca22015-04-21 22:11:234762 // CONNECT to www.example.org:443 via SPDY
bncdf80d44fd2016-07-15 20:27:414763 SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234764 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:414765 SpdySerializedFrame get(
[email protected]c10b20852013-05-15 21:29:204766 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]d9da5fe2010-10-13 22:37:164767
4768 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414769 CreateMockWrite(connect, 0), CreateMockWrite(get, 2),
[email protected]d9da5fe2010-10-13 22:37:164770 };
4771
bnc42331402016-07-25 13:36:154772 SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
bncdf80d44fd2016-07-15 20:27:414773 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]d9da5fe2010-10-13 22:37:164774 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414775 CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 3),
[email protected]d9da5fe2010-10-13 22:37:164776 };
4777
rch8e6c6c42015-05-01 14:05:134778 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4779 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:074780 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d9da5fe2010-10-13 22:37:164781
[email protected]8ddf8322012-02-23 18:08:064782 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364783 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:074784 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:064785 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364786 ssl2.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:074787 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]d9da5fe2010-10-13 22:37:164788
[email protected]49639fa2011-12-20 23:22:414789 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:164790
[email protected]49639fa2011-12-20 23:22:414791 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:014792 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]d9da5fe2010-10-13 22:37:164793
4794 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:014795 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]d9da5fe2010-10-13 22:37:164796
ttuttle960fcbf2016-04-19 13:26:324797 // TODO(juliatuttle): Anything else to check here?
[email protected]d9da5fe2010-10-13 22:37:164798}
4799
[email protected]f6c63db52013-02-02 00:35:224800// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4801// HTTPS Proxy to different servers.
bncd16676a2016-07-20 16:23:014802TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224803 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
4804 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034805 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514806 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074807 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094808 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504809 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224810
4811 HttpRequestInfo request1;
4812 request1.method = "GET";
bncce36dca22015-04-21 22:11:234813 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224814 request1.load_flags = 0;
4815
4816 HttpRequestInfo request2;
4817 request2.method = "GET";
bncce36dca22015-04-21 22:11:234818 request2.url = GURL("https://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:224819 request2.load_flags = 0;
4820
bncce36dca22015-04-21 22:11:234821 // CONNECT to www.example.org:443 via SPDY.
bncdf80d44fd2016-07-15 20:27:414822 SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234823 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bnc42331402016-07-25 13:36:154824 SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224825
bncce36dca22015-04-21 22:11:234826 // Fetch https://www.example.org/ via HTTP.
4827 const char get1[] =
4828 "GET / HTTP/1.1\r\n"
4829 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224830 "Connection: keep-alive\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414831 SpdySerializedFrame wrapped_get1(
4832 spdy_util_.ConstructSpdyDataFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224833 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4834 "Content-Length: 1\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414835 SpdySerializedFrame wrapped_get_resp1(
4836 spdy_util_.ConstructSpdyDataFrame(1, resp1, strlen(resp1), false));
4837 SpdySerializedFrame wrapped_body1(
4838 spdy_util_.ConstructSpdyDataFrame(1, "1", 1, false));
4839 SpdySerializedFrame window_update(
4840 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:224841
bncce36dca22015-04-21 22:11:234842 // CONNECT to mail.example.org:443 via SPDY.
[email protected]745aa9c2014-06-27 02:21:294843 SpdyHeaderBlock connect2_block;
[email protected]745aa9c2014-06-27 02:21:294844 connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
bnca9b9e222016-07-11 20:10:404845 connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443";
bnc42331402016-07-25 13:36:154846 SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
4847 3, std::move(connect2_block), LOWEST, false));
[email protected]601e03f12014-04-06 16:26:394848
bnc42331402016-07-25 13:36:154849 SpdySerializedFrame conn_resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
[email protected]f6c63db52013-02-02 00:35:224850
bncce36dca22015-04-21 22:11:234851 // Fetch https://mail.example.org/ via HTTP.
4852 const char get2[] =
4853 "GET / HTTP/1.1\r\n"
4854 "Host: mail.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224855 "Connection: keep-alive\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414856 SpdySerializedFrame wrapped_get2(
4857 spdy_util_.ConstructSpdyDataFrame(3, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224858 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4859 "Content-Length: 2\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414860 SpdySerializedFrame wrapped_get_resp2(
4861 spdy_util_.ConstructSpdyDataFrame(3, resp2, strlen(resp2), false));
4862 SpdySerializedFrame wrapped_body2(
4863 spdy_util_.ConstructSpdyDataFrame(3, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224864
4865 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414866 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
4867 CreateMockWrite(connect2, 5), CreateMockWrite(wrapped_get2, 7),
[email protected]f6c63db52013-02-02 00:35:224868 };
4869
4870 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414871 CreateMockRead(conn_resp1, 1, ASYNC),
4872 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
4873 CreateMockRead(wrapped_body1, 4, ASYNC),
4874 CreateMockRead(conn_resp2, 6, ASYNC),
4875 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
4876 CreateMockRead(wrapped_body2, 9, ASYNC),
4877 MockRead(ASYNC, 0, 10),
[email protected]f6c63db52013-02-02 00:35:224878 };
4879
mmenke11eb5152015-06-09 14:50:504880 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4881 arraysize(spdy_writes));
4882 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:224883
4884 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:364885 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:504886 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:224887 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504888 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:224889 SSLSocketDataProvider ssl3(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:504890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
[email protected]f6c63db52013-02-02 00:35:224891
4892 TestCompletionCallback callback;
4893
danakj1fd259a02016-04-16 03:17:094894 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:504895 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224896 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014897 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:224898
4899 LoadTimingInfo load_timing_info;
4900 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4901 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
4902
4903 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:524904 ASSERT_TRUE(response);
4905 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:224906 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4907
4908 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:294909 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:504910 rv = trans->Read(buf.get(), 256, callback.callback());
4911 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224912
danakj1fd259a02016-04-16 03:17:094913 std::unique_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:504914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:224915 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:014916 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:224917
4918 LoadTimingInfo load_timing_info2;
4919 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
4920 // Even though the SPDY connection is reused, a new tunnelled connection has
4921 // to be created, so the socket's load timing looks like a fresh connection.
4922 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
4923
4924 // The requests should have different IDs, since they each are using their own
4925 // separate stream.
4926 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
4927
mmenke11eb5152015-06-09 14:50:504928 rv = trans2->Read(buf.get(), 256, callback.callback());
4929 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:224930}
4931
4932// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4933// HTTPS Proxy to the same server.
bncd16676a2016-07-20 16:23:014934TEST_F(HttpNetworkTransactionTest,
[email protected]f6c63db52013-02-02 00:35:224935 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
4936 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:034937 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:514938 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:074939 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:094940 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:504941 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:224942
4943 HttpRequestInfo request1;
4944 request1.method = "GET";
bncce36dca22015-04-21 22:11:234945 request1.url = GURL("https://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:224946 request1.load_flags = 0;
4947
4948 HttpRequestInfo request2;
4949 request2.method = "GET";
bncce36dca22015-04-21 22:11:234950 request2.url = GURL("https://www.example.org/2");
[email protected]f6c63db52013-02-02 00:35:224951 request2.load_flags = 0;
4952
bncce36dca22015-04-21 22:11:234953 // CONNECT to www.example.org:443 via SPDY.
bncdf80d44fd2016-07-15 20:27:414954 SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234955 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bnc42331402016-07-25 13:36:154956 SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]f6c63db52013-02-02 00:35:224957
bncce36dca22015-04-21 22:11:234958 // Fetch https://www.example.org/ via HTTP.
4959 const char get1[] =
4960 "GET / HTTP/1.1\r\n"
4961 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224962 "Connection: keep-alive\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414963 SpdySerializedFrame wrapped_get1(
4964 spdy_util_.ConstructSpdyDataFrame(1, get1, strlen(get1), false));
[email protected]f6c63db52013-02-02 00:35:224965 const char resp1[] = "HTTP/1.1 200 OK\r\n"
4966 "Content-Length: 1\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414967 SpdySerializedFrame wrapped_get_resp1(
4968 spdy_util_.ConstructSpdyDataFrame(1, resp1, strlen(resp1), false));
4969 SpdySerializedFrame wrapped_body1(
4970 spdy_util_.ConstructSpdyDataFrame(1, "1", 1, false));
4971 SpdySerializedFrame window_update(
4972 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1.size()));
[email protected]f6c63db52013-02-02 00:35:224973
bncce36dca22015-04-21 22:11:234974 // Fetch https://www.example.org/2 via HTTP.
4975 const char get2[] =
4976 "GET /2 HTTP/1.1\r\n"
4977 "Host: www.example.org\r\n"
[email protected]f6c63db52013-02-02 00:35:224978 "Connection: keep-alive\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414979 SpdySerializedFrame wrapped_get2(
4980 spdy_util_.ConstructSpdyDataFrame(1, get2, strlen(get2), false));
[email protected]f6c63db52013-02-02 00:35:224981 const char resp2[] = "HTTP/1.1 200 OK\r\n"
4982 "Content-Length: 2\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:414983 SpdySerializedFrame wrapped_get_resp2(
4984 spdy_util_.ConstructSpdyDataFrame(1, resp2, strlen(resp2), false));
4985 SpdySerializedFrame wrapped_body2(
4986 spdy_util_.ConstructSpdyDataFrame(1, "22", 2, false));
[email protected]f6c63db52013-02-02 00:35:224987
4988 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:414989 CreateMockWrite(connect1, 0), CreateMockWrite(wrapped_get1, 2),
4990 CreateMockWrite(wrapped_get2, 5),
[email protected]f6c63db52013-02-02 00:35:224991 };
4992
4993 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:414994 CreateMockRead(conn_resp1, 1, ASYNC),
4995 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
4996 CreateMockRead(wrapped_body1, 4, ASYNC),
4997 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
4998 CreateMockRead(wrapped_body2, 7, ASYNC),
4999 MockRead(ASYNC, 0, 8),
[email protected]f6c63db52013-02-02 00:35:225000 };
5001
mmenke11eb5152015-06-09 14:50:505002 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
5003 arraysize(spdy_writes));
5004 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:225005
5006 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365007 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:505008 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:225009 SSLSocketDataProvider ssl2(ASYNC, OK);
mmenke11eb5152015-06-09 14:50:505010 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]f6c63db52013-02-02 00:35:225011
5012 TestCompletionCallback callback;
5013
danakj1fd259a02016-04-16 03:17:095014 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505015 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:225016 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015017 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:225018
5019 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015020 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:225021
5022 LoadTimingInfo load_timing_info;
5023 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5024 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
5025
5026 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525027 ASSERT_TRUE(response);
5028 ASSERT_TRUE(response->headers);
[email protected]f6c63db52013-02-02 00:35:225029 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5030
5031 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:295032 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
[email protected]90499482013-06-01 00:39:505033 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:225034 trans.reset();
5035
danakj1fd259a02016-04-16 03:17:095036 std::unique_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:505037 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:225038 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015039 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f6c63db52013-02-02 00:35:225040
[email protected]f6c63db52013-02-02 00:35:225041 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015042 EXPECT_THAT(rv, IsOk());
[email protected]f6c63db52013-02-02 00:35:225043
5044 LoadTimingInfo load_timing_info2;
5045 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5046 TestLoadTimingReused(load_timing_info2);
5047
5048 // The requests should have the same ID.
5049 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
5050
[email protected]90499482013-06-01 00:39:505051 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
[email protected]f6c63db52013-02-02 00:35:225052}
5053
5054// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
5055// Proxy to different servers.
bncd16676a2016-07-20 16:23:015056TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
[email protected]f6c63db52013-02-02 00:35:225057 // Configure against https proxy server "proxy:70".
rdsmith82957ad2015-09-16 19:42:035058 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:515059 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075060 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095061 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:505062 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]f6c63db52013-02-02 00:35:225063
5064 HttpRequestInfo request1;
5065 request1.method = "GET";
bncce36dca22015-04-21 22:11:235066 request1.url = GURL("http://www.example.org/");
[email protected]f6c63db52013-02-02 00:35:225067 request1.load_flags = 0;
5068
5069 HttpRequestInfo request2;
5070 request2.method = "GET";
bncce36dca22015-04-21 22:11:235071 request2.url = GURL("http://mail.example.org/");
[email protected]f6c63db52013-02-02 00:35:225072 request2.load_flags = 0;
5073
bncce36dca22015-04-21 22:11:235074 // http://www.example.org/
bnc086b39e12016-06-24 13:05:265075 SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:235076 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
bncdf80d44fd2016-07-15 20:27:415077 SpdySerializedFrame get1(
bnc42331402016-07-25 13:36:155078 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
5079 SpdySerializedFrame get_resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:415080 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, "1", 1, true));
rdsmithebb50aa2015-11-12 03:44:385081 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]f6c63db52013-02-02 00:35:225082
bncce36dca22015-04-21 22:11:235083 // http://mail.example.org/
bnc086b39e12016-06-24 13:05:265084 SpdyHeaderBlock headers2(
bncce36dca22015-04-21 22:11:235085 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
bncdf80d44fd2016-07-15 20:27:415086 SpdySerializedFrame get2(
bnc42331402016-07-25 13:36:155087 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
5088 SpdySerializedFrame get_resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:415089 SpdySerializedFrame body2(
5090 spdy_util_.ConstructSpdyDataFrame(3, "22", 2, true));
[email protected]f6c63db52013-02-02 00:35:225091
5092 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:415093 CreateMockWrite(get1, 0), CreateMockWrite(get2, 3),
[email protected]f6c63db52013-02-02 00:35:225094 };
5095
5096 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:415097 CreateMockRead(get_resp1, 1, ASYNC),
5098 CreateMockRead(body1, 2, ASYNC),
5099 CreateMockRead(get_resp2, 4, ASYNC),
5100 CreateMockRead(body2, 5, ASYNC),
5101 MockRead(ASYNC, 0, 6),
[email protected]f6c63db52013-02-02 00:35:225102 };
5103
mmenke11eb5152015-06-09 14:50:505104 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
5105 arraysize(spdy_writes));
5106 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]f6c63db52013-02-02 00:35:225107
5108 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:365109 ssl.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:505110 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]f6c63db52013-02-02 00:35:225111
5112 TestCompletionCallback callback;
5113
danakj1fd259a02016-04-16 03:17:095114 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505115 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:225116 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015117 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:225118
5119 LoadTimingInfo load_timing_info;
5120 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5121 TestLoadTimingNotReused(load_timing_info,
5122 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5123
5124 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525125 ASSERT_TRUE(response);
5126 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:025127 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]f6c63db52013-02-02 00:35:225128
5129 std::string response_data;
ttuttle859dc7a2015-04-23 19:42:295130 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
mmenke11eb5152015-06-09 14:50:505131 rv = trans->Read(buf.get(), 256, callback.callback());
5132 EXPECT_EQ(1, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225133 // Delete the first request, so the second one can reuse the socket.
5134 trans.reset();
5135
danakj1fd259a02016-04-16 03:17:095136 std::unique_ptr<HttpTransaction> trans2(
[email protected]90499482013-06-01 00:39:505137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f6c63db52013-02-02 00:35:225138 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015139 EXPECT_THAT(callback.GetResult(rv), IsOk());
[email protected]f6c63db52013-02-02 00:35:225140
5141 LoadTimingInfo load_timing_info2;
5142 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
5143 TestLoadTimingReused(load_timing_info2);
5144
5145 // The requests should have the same ID.
5146 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
5147
mmenke11eb5152015-06-09 14:50:505148 rv = trans2->Read(buf.get(), 256, callback.callback());
5149 EXPECT_EQ(2, callback.GetResult(rv));
[email protected]f6c63db52013-02-02 00:35:225150}
5151
[email protected]2df19bb2010-08-25 20:13:465152// Test the challenge-response-retry sequence through an HTTPS Proxy
bncd16676a2016-07-20 16:23:015153TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:465154 HttpRequestInfo request;
5155 request.method = "GET";
bncce36dca22015-04-21 22:11:235156 request.url = GURL("http://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:465157 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:295158 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2df19bb2010-08-25 20:13:465159
[email protected]79cb5c12011-09-12 13:12:045160 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035161 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
vishal.b62985ca92015-04-17 08:45:515162 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:075163 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:095164 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275165
[email protected]2df19bb2010-08-25 20:13:465166 // Since we have proxy, should use full url
5167 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235168 MockWrite(
5169 "GET http://www.example.org/ HTTP/1.1\r\n"
5170 "Host: www.example.org\r\n"
5171 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465172
bncce36dca22015-04-21 22:11:235173 // After calling trans->RestartWithAuth(), this is the request we should
5174 // be issuing -- the final header line contains the credentials.
5175 MockWrite(
5176 "GET http://www.example.org/ HTTP/1.1\r\n"
5177 "Host: www.example.org\r\n"
5178 "Proxy-Connection: keep-alive\r\n"
5179 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:465180 };
5181
5182 // The proxy responds to the GET with a 407, using a persistent
5183 // connection.
5184 MockRead data_reads1[] = {
5185 // No credentials.
5186 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5187 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5188 MockRead("Proxy-Connection: keep-alive\r\n"),
5189 MockRead("Content-Length: 0\r\n\r\n"),
5190
5191 MockRead("HTTP/1.1 200 OK\r\n"),
5192 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5193 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065194 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:465195 };
5196
5197 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5198 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:075199 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:065200 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:075201 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:465202
[email protected]49639fa2011-12-20 23:22:415203 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:465204
danakj1fd259a02016-04-16 03:17:095205 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505206 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505207
[email protected]49639fa2011-12-20 23:22:415208 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:015209 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465210
5211 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015212 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465213
[email protected]58e32bb2013-01-21 18:23:255214 LoadTimingInfo load_timing_info;
5215 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5216 TestLoadTimingNotReused(load_timing_info,
5217 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
5218
[email protected]2df19bb2010-08-25 20:13:465219 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525220 ASSERT_TRUE(response);
5221 ASSERT_TRUE(response->headers);
[email protected]2df19bb2010-08-25 20:13:465222 EXPECT_EQ(407, response->headers->response_code());
5223 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
asanka098c0092016-06-16 20:18:435224 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:465225
[email protected]49639fa2011-12-20 23:22:415226 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:465227
[email protected]49639fa2011-12-20 23:22:415228 rv = trans->RestartWithAuth(
5229 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015230 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:465231
5232 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015233 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:465234
[email protected]58e32bb2013-01-21 18:23:255235 load_timing_info = LoadTimingInfo();
5236 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5237 // Retrying with HTTP AUTH is considered to be reusing a socket.
5238 TestLoadTimingReused(load_timing_info);
5239
[email protected]2df19bb2010-08-25 20:13:465240 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525241 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:465242
5243 EXPECT_TRUE(response->headers->IsKeepAlive());
5244 EXPECT_EQ(200, response->headers->response_code());
5245 EXPECT_EQ(100, response->headers->GetContentLength());
5246 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5247
5248 // The password prompt info should not be set.
wezca1070932016-05-26 20:30:525249 EXPECT_FALSE(response->auth_challenge);
[email protected]2df19bb2010-08-25 20:13:465250}
5251
[email protected]23e482282013-06-14 16:08:025252void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:085253 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:425254 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:085255 request.method = "GET";
bncce36dca22015-04-21 22:11:235256 request.url = GURL("https://www.example.org/");
[email protected]c744cf22009-02-27 07:28:085257 request.load_flags = 0;
5258
[email protected]cb9bf6ca2011-01-28 13:15:275259 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035260 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
danakj1fd259a02016-04-16 03:17:095261 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275262
[email protected]c744cf22009-02-27 07:28:085263 // Since we have proxy, should try to establish tunnel.
5264 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:175265 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5266 "Host: www.example.org:443\r\n"
5267 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:085268 };
5269
5270 MockRead data_reads[] = {
mmenked39192ee2015-12-09 00:57:235271 status, MockRead("Content-Length: 10\r\n\r\n"),
5272 // No response body because the test stops reading here.
5273 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]c744cf22009-02-27 07:28:085274 };
5275
[email protected]31a2bfe2010-02-09 08:03:395276 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5277 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:075278 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:085279
[email protected]49639fa2011-12-20 23:22:415280 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:085281
danakj1fd259a02016-04-16 03:17:095282 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505283 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505284
[email protected]49639fa2011-12-20 23:22:415285 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015286 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]c744cf22009-02-27 07:28:085287
5288 rv = callback.WaitForResult();
5289 EXPECT_EQ(expected_status, rv);
5290}
5291
[email protected]23e482282013-06-14 16:08:025292void HttpNetworkTransactionTest::ConnectStatusHelper(
[email protected]448d4ca52012-03-04 04:12:235293 const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:085294 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:425295 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:085296}
5297
bncd16676a2016-07-20 16:23:015298TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
[email protected]c744cf22009-02-27 07:28:085299 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
5300}
5301
bncd16676a2016-07-20 16:23:015302TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
[email protected]c744cf22009-02-27 07:28:085303 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
5304}
5305
bncd16676a2016-07-20 16:23:015306TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
[email protected]c744cf22009-02-27 07:28:085307 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
5308}
5309
bncd16676a2016-07-20 16:23:015310TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
[email protected]c744cf22009-02-27 07:28:085311 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
5312}
5313
bncd16676a2016-07-20 16:23:015314TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
[email protected]c744cf22009-02-27 07:28:085315 ConnectStatusHelper(
5316 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
5317}
5318
bncd16676a2016-07-20 16:23:015319TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
[email protected]c744cf22009-02-27 07:28:085320 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
5321}
5322
bncd16676a2016-07-20 16:23:015323TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
[email protected]c744cf22009-02-27 07:28:085324 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
5325}
5326
bncd16676a2016-07-20 16:23:015327TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
[email protected]c744cf22009-02-27 07:28:085328 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
5329}
5330
bncd16676a2016-07-20 16:23:015331TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
[email protected]c744cf22009-02-27 07:28:085332 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
5333}
5334
bncd16676a2016-07-20 16:23:015335TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
[email protected]c744cf22009-02-27 07:28:085336 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
5337}
5338
bncd16676a2016-07-20 16:23:015339TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
[email protected]c744cf22009-02-27 07:28:085340 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
5341}
5342
bncd16676a2016-07-20 16:23:015343TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
[email protected]c744cf22009-02-27 07:28:085344 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
5345}
5346
bncd16676a2016-07-20 16:23:015347TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
[email protected]c744cf22009-02-27 07:28:085348 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
5349}
5350
bncd16676a2016-07-20 16:23:015351TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
[email protected]c744cf22009-02-27 07:28:085352 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
5353}
5354
bncd16676a2016-07-20 16:23:015355TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
[email protected]c744cf22009-02-27 07:28:085356 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
5357}
5358
bncd16676a2016-07-20 16:23:015359TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
[email protected]c744cf22009-02-27 07:28:085360 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
5361}
5362
bncd16676a2016-07-20 16:23:015363TEST_F(HttpNetworkTransactionTest, ConnectStatus308) {
[email protected]0a17aab32014-04-24 03:32:375364 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
5365}
5366
bncd16676a2016-07-20 16:23:015367TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
[email protected]c744cf22009-02-27 07:28:085368 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
5369}
5370
bncd16676a2016-07-20 16:23:015371TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
[email protected]c744cf22009-02-27 07:28:085372 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
5373}
5374
bncd16676a2016-07-20 16:23:015375TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
[email protected]c744cf22009-02-27 07:28:085376 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
5377}
5378
bncd16676a2016-07-20 16:23:015379TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
[email protected]c744cf22009-02-27 07:28:085380 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
5381}
5382
bncd16676a2016-07-20 16:23:015383TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
[email protected]c744cf22009-02-27 07:28:085384 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
5385}
5386
bncd16676a2016-07-20 16:23:015387TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
[email protected]c744cf22009-02-27 07:28:085388 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
5389}
5390
bncd16676a2016-07-20 16:23:015391TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
[email protected]c744cf22009-02-27 07:28:085392 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
5393}
5394
bncd16676a2016-07-20 16:23:015395TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
[email protected]c744cf22009-02-27 07:28:085396 ConnectStatusHelperWithExpectedStatus(
5397 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:545398 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:085399}
5400
bncd16676a2016-07-20 16:23:015401TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
[email protected]c744cf22009-02-27 07:28:085402 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
5403}
5404
bncd16676a2016-07-20 16:23:015405TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
[email protected]c744cf22009-02-27 07:28:085406 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
5407}
5408
bncd16676a2016-07-20 16:23:015409TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
[email protected]c744cf22009-02-27 07:28:085410 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
5411}
5412
bncd16676a2016-07-20 16:23:015413TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
[email protected]c744cf22009-02-27 07:28:085414 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
5415}
5416
bncd16676a2016-07-20 16:23:015417TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
[email protected]c744cf22009-02-27 07:28:085418 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
5419}
5420
bncd16676a2016-07-20 16:23:015421TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
[email protected]c744cf22009-02-27 07:28:085422 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
5423}
5424
bncd16676a2016-07-20 16:23:015425TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
[email protected]c744cf22009-02-27 07:28:085426 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
5427}
5428
bncd16676a2016-07-20 16:23:015429TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
[email protected]c744cf22009-02-27 07:28:085430 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
5431}
5432
bncd16676a2016-07-20 16:23:015433TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
[email protected]c744cf22009-02-27 07:28:085434 ConnectStatusHelper(
5435 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
5436}
5437
bncd16676a2016-07-20 16:23:015438TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
[email protected]c744cf22009-02-27 07:28:085439 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
5440}
5441
bncd16676a2016-07-20 16:23:015442TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
[email protected]c744cf22009-02-27 07:28:085443 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
5444}
5445
bncd16676a2016-07-20 16:23:015446TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
[email protected]c744cf22009-02-27 07:28:085447 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
5448}
5449
bncd16676a2016-07-20 16:23:015450TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
[email protected]c744cf22009-02-27 07:28:085451 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
5452}
5453
bncd16676a2016-07-20 16:23:015454TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
[email protected]c744cf22009-02-27 07:28:085455 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
5456}
5457
bncd16676a2016-07-20 16:23:015458TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
[email protected]c744cf22009-02-27 07:28:085459 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
5460}
5461
bncd16676a2016-07-20 16:23:015462TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
[email protected]c744cf22009-02-27 07:28:085463 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
5464}
5465
[email protected]038e9a32008-10-08 22:40:165466// Test the flow when both the proxy server AND origin server require
5467// authentication. Again, this uses basic auth for both since that is
5468// the simplest to mock.
bncd16676a2016-07-20 16:23:015469TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:275470 HttpRequestInfo request;
5471 request.method = "GET";
bncce36dca22015-04-21 22:11:235472 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275473 request.load_flags = 0;
5474
[email protected]038e9a32008-10-08 22:40:165475 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035476 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
danakj1fd259a02016-04-16 03:17:095477 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3fe8d2f82013-10-17 08:56:075478
danakj1fd259a02016-04-16 03:17:095479 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415480 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]038e9a32008-10-08 22:40:165481
[email protected]f9ee6b52008-11-08 06:46:235482 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:235483 MockWrite(
5484 "GET http://www.example.org/ HTTP/1.1\r\n"
5485 "Host: www.example.org\r\n"
5486 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:235487 };
5488
[email protected]038e9a32008-10-08 22:40:165489 MockRead data_reads1[] = {
5490 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
5491 // Give a couple authenticate options (only the middle one is actually
5492 // supported).
[email protected]22927ad2009-09-21 19:56:195493 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:165494 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5495 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
5496 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5497 // Large content-length -- won't matter, as connection will be reset.
5498 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065499 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:165500 };
5501
5502 // After calling trans->RestartWithAuth() the first time, this is the
5503 // request we should be issuing -- the final header line contains the
5504 // proxy's credentials.
5505 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:235506 MockWrite(
5507 "GET http://www.example.org/ HTTP/1.1\r\n"
5508 "Host: www.example.org\r\n"
5509 "Proxy-Connection: keep-alive\r\n"
5510 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165511 };
5512
5513 // Now the proxy server lets the request pass through to origin server.
5514 // The origin server responds with a 401.
5515 MockRead data_reads2[] = {
5516 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5517 // Note: We are using the same realm-name as the proxy server. This is
5518 // completely valid, as realms are unique across hosts.
5519 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5520 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5521 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065522 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:165523 };
5524
5525 // After calling trans->RestartWithAuth() the second time, we should send
5526 // the credentials for both the proxy and origin server.
5527 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:235528 MockWrite(
5529 "GET http://www.example.org/ HTTP/1.1\r\n"
5530 "Host: www.example.org\r\n"
5531 "Proxy-Connection: keep-alive\r\n"
5532 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
5533 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]038e9a32008-10-08 22:40:165534 };
5535
5536 // Lastly we get the desired content.
5537 MockRead data_reads3[] = {
5538 MockRead("HTTP/1.0 200 OK\r\n"),
5539 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5540 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065541 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:165542 };
5543
[email protected]31a2bfe2010-02-09 08:03:395544 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5545 data_writes1, arraysize(data_writes1));
5546 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5547 data_writes2, arraysize(data_writes2));
5548 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5549 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075550 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5551 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5552 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:165553
[email protected]49639fa2011-12-20 23:22:415554 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:165555
[email protected]49639fa2011-12-20 23:22:415556 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015557 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:165558
5559 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015560 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:165561
[email protected]1c773ea12009-04-28 19:58:425562 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525563 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:045564 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165565
[email protected]49639fa2011-12-20 23:22:415566 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:165567
[email protected]49639fa2011-12-20 23:22:415568 rv = trans->RestartWithAuth(
5569 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:015570 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:165571
5572 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015573 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:165574
5575 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525576 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:045577 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:165578
[email protected]49639fa2011-12-20 23:22:415579 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:165580
[email protected]49639fa2011-12-20 23:22:415581 rv = trans->RestartWithAuth(
5582 AuthCredentials(kFoo2, kBar2), callback3.callback());
robpercival214763f2016-07-01 23:27:015583 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]038e9a32008-10-08 22:40:165584
5585 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:015586 EXPECT_THAT(rv, IsOk());
[email protected]038e9a32008-10-08 22:40:165587
5588 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525589 EXPECT_FALSE(response->auth_challenge);
[email protected]038e9a32008-10-08 22:40:165590 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:165591}
[email protected]4ddaf2502008-10-23 18:26:195592
[email protected]ea9dc9a2009-09-05 00:43:325593// For the NTLM implementation using SSPI, we skip the NTLM tests since we
5594// can't hook into its internals to cause it to generate predictable NTLM
5595// authorization headers.
5596#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:295597// The NTLM authentication unit tests were generated by capturing the HTTP
5598// requests and responses using Fiddler 2 and inspecting the generated random
5599// bytes in the debugger.
5600
5601// Enter the correct password and authenticate successfully.
bncd16676a2016-07-20 16:23:015602TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:425603 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:245604 request.method = "GET";
5605 request.url = GURL("http://172.22.68.17/kids/login.aspx");
[email protected]2217aa22013-10-11 03:03:545606
5607 // Ensure load is not disrupted by flags which suppress behaviour specific
5608 // to other auth schemes.
5609 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
[email protected]3f918782009-02-28 01:29:245610
[email protected]cb9bf6ca2011-01-28 13:15:275611 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
5612 MockGetHostName);
danakj1fd259a02016-04-16 03:17:095613 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275614
[email protected]3f918782009-02-28 01:29:245615 MockWrite data_writes1[] = {
5616 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5617 "Host: 172.22.68.17\r\n"
5618 "Connection: keep-alive\r\n\r\n"),
5619 };
5620
5621 MockRead data_reads1[] = {
5622 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045623 // Negotiate and NTLM are often requested together. However, we only want
5624 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5625 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:245626 MockRead("WWW-Authenticate: NTLM\r\n"),
5627 MockRead("Connection: close\r\n"),
5628 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365629 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245630 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065631 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:245632 };
5633
5634 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225635 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:245636 // request we should be issuing -- the final header line contains a Type
5637 // 1 message.
5638 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5639 "Host: 172.22.68.17\r\n"
5640 "Connection: keep-alive\r\n"
5641 "Authorization: NTLM "
5642 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5643
5644 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5645 // (the credentials for the origin server). The second request continues
5646 // on the same connection.
5647 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5648 "Host: 172.22.68.17\r\n"
5649 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:295650 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5651 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5652 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
5653 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
5654 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245655 };
5656
5657 MockRead data_reads2[] = {
5658 // The origin server responds with a Type 2 message.
5659 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5660 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:295661 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:245662 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5663 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5664 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5665 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5666 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5667 "BtAAAAAAA=\r\n"),
5668 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365669 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:245670 MockRead("You are not authorized to view this page\r\n"),
5671
5672 // Lastly we get the desired content.
5673 MockRead("HTTP/1.1 200 OK\r\n"),
5674 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5675 MockRead("Content-Length: 13\r\n\r\n"),
5676 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065677 MockRead(SYNCHRONOUS, OK),
[email protected]3f918782009-02-28 01:29:245678 };
5679
[email protected]31a2bfe2010-02-09 08:03:395680 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5681 data_writes1, arraysize(data_writes1));
5682 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5683 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:075684 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5685 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:245686
[email protected]49639fa2011-12-20 23:22:415687 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:245688
danakj1fd259a02016-04-16 03:17:095689 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505690 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505691
[email protected]49639fa2011-12-20 23:22:415692 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:245694
5695 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015696 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:245697
[email protected]0757e7702009-03-27 04:00:225698 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5699
[email protected]1c773ea12009-04-28 19:58:425700 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525701 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:045702 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:245703
[email protected]49639fa2011-12-20 23:22:415704 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:255705
[email protected]f3cf9802011-10-28 18:44:585706 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415707 callback2.callback());
robpercival214763f2016-07-01 23:27:015708 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:255709
5710 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015711 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:255712
5713 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5714
5715 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525716 ASSERT_TRUE(response);
5717 EXPECT_FALSE(response->auth_challenge);
[email protected]10af5fe72011-01-31 16:17:255718
[email protected]49639fa2011-12-20 23:22:415719 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:245720
[email protected]49639fa2011-12-20 23:22:415721 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:015722 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3f918782009-02-28 01:29:245723
[email protected]0757e7702009-03-27 04:00:225724 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:015725 EXPECT_THAT(rv, IsOk());
[email protected]3f918782009-02-28 01:29:245726
5727 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525728 ASSERT_TRUE(response);
5729 EXPECT_FALSE(response->auth_challenge);
[email protected]3f918782009-02-28 01:29:245730 EXPECT_EQ(13, response->headers->GetContentLength());
5731}
5732
[email protected]385a4672009-03-11 22:21:295733// Enter a wrong password, and then the correct one.
bncd16676a2016-07-20 16:23:015734TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:425735 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:295736 request.method = "GET";
5737 request.url = GURL("http://172.22.68.17/kids/login.aspx");
5738 request.load_flags = 0;
5739
[email protected]cb9bf6ca2011-01-28 13:15:275740 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
5741 MockGetHostName);
danakj1fd259a02016-04-16 03:17:095742 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:275743
[email protected]385a4672009-03-11 22:21:295744 MockWrite data_writes1[] = {
5745 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5746 "Host: 172.22.68.17\r\n"
5747 "Connection: keep-alive\r\n\r\n"),
5748 };
5749
5750 MockRead data_reads1[] = {
5751 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:045752 // Negotiate and NTLM are often requested together. However, we only want
5753 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
5754 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:295755 MockRead("WWW-Authenticate: NTLM\r\n"),
5756 MockRead("Connection: close\r\n"),
5757 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365758 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295759 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065760 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295761 };
5762
5763 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:225764 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295765 // request we should be issuing -- the final header line contains a Type
5766 // 1 message.
5767 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5768 "Host: 172.22.68.17\r\n"
5769 "Connection: keep-alive\r\n"
5770 "Authorization: NTLM "
5771 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5772
5773 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5774 // (the credentials for the origin server). The second request continues
5775 // on the same connection.
5776 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5777 "Host: 172.22.68.17\r\n"
5778 "Connection: keep-alive\r\n"
5779 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5780 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5781 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
5782 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
5783 "4Ww7b7E=\r\n\r\n"),
5784 };
5785
5786 MockRead data_reads2[] = {
5787 // The origin server responds with a Type 2 message.
5788 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5789 MockRead("WWW-Authenticate: NTLM "
5790 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
5791 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5792 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5793 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5794 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5795 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5796 "BtAAAAAAA=\r\n"),
5797 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365798 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295799 MockRead("You are not authorized to view this page\r\n"),
5800
5801 // Wrong password.
5802 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:295803 MockRead("WWW-Authenticate: NTLM\r\n"),
5804 MockRead("Connection: close\r\n"),
5805 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365806 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295807 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:065808 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:295809 };
5810
5811 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:225812 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:295813 // request we should be issuing -- the final header line contains a Type
5814 // 1 message.
5815 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5816 "Host: 172.22.68.17\r\n"
5817 "Connection: keep-alive\r\n"
5818 "Authorization: NTLM "
5819 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
5820
5821 // After calling trans->RestartWithAuth(), we should send a Type 3 message
5822 // (the credentials for the origin server). The second request continues
5823 // on the same connection.
5824 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
5825 "Host: 172.22.68.17\r\n"
5826 "Connection: keep-alive\r\n"
5827 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
5828 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
5829 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
5830 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
5831 "+4MUm7c=\r\n\r\n"),
5832 };
5833
5834 MockRead data_reads3[] = {
5835 // The origin server responds with a Type 2 message.
5836 MockRead("HTTP/1.1 401 Access Denied\r\n"),
5837 MockRead("WWW-Authenticate: NTLM "
5838 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
5839 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
5840 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
5841 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
5842 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
5843 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
5844 "BtAAAAAAA=\r\n"),
5845 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:365846 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:295847 MockRead("You are not authorized to view this page\r\n"),
5848
5849 // Lastly we get the desired content.
5850 MockRead("HTTP/1.1 200 OK\r\n"),
5851 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
5852 MockRead("Content-Length: 13\r\n\r\n"),
5853 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:065854 MockRead(SYNCHRONOUS, OK),
[email protected]385a4672009-03-11 22:21:295855 };
5856
[email protected]31a2bfe2010-02-09 08:03:395857 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5858 data_writes1, arraysize(data_writes1));
5859 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5860 data_writes2, arraysize(data_writes2));
5861 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5862 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:075863 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5864 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5865 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:295866
[email protected]49639fa2011-12-20 23:22:415867 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:295868
danakj1fd259a02016-04-16 03:17:095869 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505870 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:505871
[email protected]49639fa2011-12-20 23:22:415872 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015873 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:295874
5875 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:015876 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:295877
[email protected]0757e7702009-03-27 04:00:225878 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:295879
[email protected]1c773ea12009-04-28 19:58:425880 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525881 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:045882 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:295883
[email protected]49639fa2011-12-20 23:22:415884 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:295885
[email protected]0757e7702009-03-27 04:00:225886 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:585887 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:415888 callback2.callback());
robpercival214763f2016-07-01 23:27:015889 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]385a4672009-03-11 22:21:295890
[email protected]10af5fe72011-01-31 16:17:255891 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:015892 EXPECT_THAT(rv, IsOk());
[email protected]385a4672009-03-11 22:21:295893
[email protected]0757e7702009-03-27 04:00:225894 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:415895 TestCompletionCallback callback3;
5896 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
robpercival214763f2016-07-01 23:27:015897 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:255898 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:015899 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:225900 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5901
5902 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525903 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:045904 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:225905
[email protected]49639fa2011-12-20 23:22:415906 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:225907
5908 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:585909 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:415910 callback4.callback());
robpercival214763f2016-07-01 23:27:015911 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]10af5fe72011-01-31 16:17:255912
5913 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:015914 EXPECT_THAT(rv, IsOk());
[email protected]10af5fe72011-01-31 16:17:255915
5916 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5917
[email protected]49639fa2011-12-20 23:22:415918 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:255919
5920 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:415921 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
robpercival214763f2016-07-01 23:27:015922 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:225923
5924 rv = callback5.WaitForResult();
robpercival214763f2016-07-01 23:27:015925 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:225926
[email protected]385a4672009-03-11 22:21:295927 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:525928 EXPECT_FALSE(response->auth_challenge);
[email protected]385a4672009-03-11 22:21:295929 EXPECT_EQ(13, response->headers->GetContentLength());
5930}
[email protected]ea9dc9a2009-09-05 00:43:325931#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:295932
[email protected]4ddaf2502008-10-23 18:26:195933// Test reading a server response which has only headers, and no body.
5934// After some maximum number of bytes is consumed, the transaction should
5935// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
bncd16676a2016-07-20 16:23:015936TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:425937 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:195938 request.method = "GET";
bncce36dca22015-04-21 22:11:235939 request.url = GURL("http://www.example.org/");
[email protected]4ddaf2502008-10-23 18:26:195940 request.load_flags = 0;
5941
danakj1fd259a02016-04-16 03:17:095942 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5943 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:415944 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:275945
[email protected]b75b7b2f2009-10-06 00:54:535946 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:435947 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:535948 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:195949
5950 MockRead data_reads[] = {
5951 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:065952 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:195953 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:065954 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:195955 };
[email protected]31a2bfe2010-02-09 08:03:395956 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:075957 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:195958
[email protected]49639fa2011-12-20 23:22:415959 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:195960
[email protected]49639fa2011-12-20 23:22:415961 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:015962 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]4ddaf2502008-10-23 18:26:195963
5964 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:015965 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
[email protected]4ddaf2502008-10-23 18:26:195966}
[email protected]f4e426b2008-11-05 00:24:495967
5968// Make sure that we don't try to reuse a TCPClientSocket when failing to
5969// establish tunnel.
5970// http://code.google.com/p/chromium/issues/detail?id=3772
bncd16676a2016-07-20 16:23:015971TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:275972 HttpRequestInfo request;
5973 request.method = "GET";
bncce36dca22015-04-21 22:11:235974 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:275975 request.load_flags = 0;
5976
[email protected]f4e426b2008-11-05 00:24:495977 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:035978 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]db8f44c2008-12-13 04:52:015979
danakj1fd259a02016-04-16 03:17:095980 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f4e426b2008-11-05 00:24:495981
danakj1fd259a02016-04-16 03:17:095982 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:505983 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]f4e426b2008-11-05 00:24:495984
[email protected]f4e426b2008-11-05 00:24:495985 // Since we have proxy, should try to establish tunnel.
5986 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:175987 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5988 "Host: www.example.org:443\r\n"
5989 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:495990 };
5991
[email protected]77848d12008-11-14 00:00:225992 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:495993 // connection. Usually a proxy would return 501 (not implemented),
5994 // or 200 (tunnel established).
5995 MockRead data_reads1[] = {
mmenked39192ee2015-12-09 00:57:235996 MockRead("HTTP/1.1 404 Not Found\r\n"),
5997 MockRead("Content-Length: 10\r\n\r\n"),
5998 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]f4e426b2008-11-05 00:24:495999 };
6000
[email protected]31a2bfe2010-02-09 08:03:396001 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6002 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076003 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:496004
[email protected]49639fa2011-12-20 23:22:416005 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:496006
[email protected]49639fa2011-12-20 23:22:416007 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016008 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f4e426b2008-11-05 00:24:496009
6010 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016011 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]f4e426b2008-11-05 00:24:496012
[email protected]b4404c02009-04-10 16:38:526013 // Empty the current queue. This is necessary because idle sockets are
6014 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:556015 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:526016
[email protected]f4e426b2008-11-05 00:24:496017 // We now check to make sure the TCPClientSocket was not added back to
6018 // the pool.
[email protected]90499482013-06-01 00:39:506019 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:496020 trans.reset();
fdoray92e35a72016-06-10 15:54:556021 base::RunLoop().RunUntilIdle();
[email protected]f4e426b2008-11-05 00:24:496022 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]90499482013-06-01 00:39:506023 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]f4e426b2008-11-05 00:24:496024}
[email protected]372d34a2008-11-05 21:30:516025
[email protected]1b157c02009-04-21 01:55:406026// Make sure that we recycle a socket after reading all of the response body.
bncd16676a2016-07-20 16:23:016027TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:426028 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:406029 request.method = "GET";
bncce36dca22015-04-21 22:11:236030 request.url = GURL("http://www.example.org/");
[email protected]1b157c02009-04-21 01:55:406031 request.load_flags = 0;
6032
danakj1fd259a02016-04-16 03:17:096033 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276034
danakj1fd259a02016-04-16 03:17:096035 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506036 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276037
[email protected]1b157c02009-04-21 01:55:406038 MockRead data_reads[] = {
6039 // A part of the response body is received with the response headers.
6040 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
6041 // The rest of the response body is received in two parts.
6042 MockRead("lo"),
6043 MockRead(" world"),
6044 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:066045 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:406046 };
6047
[email protected]31a2bfe2010-02-09 08:03:396048 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:076049 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:406050
[email protected]49639fa2011-12-20 23:22:416051 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:406052
[email protected]49639fa2011-12-20 23:22:416053 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016054 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1b157c02009-04-21 01:55:406055
6056 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016057 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:406058
[email protected]1c773ea12009-04-28 19:58:426059 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526060 ASSERT_TRUE(response);
[email protected]1b157c02009-04-21 01:55:406061
wezca1070932016-05-26 20:30:526062 EXPECT_TRUE(response->headers);
[email protected]1b157c02009-04-21 01:55:406063 std::string status_line = response->headers->GetStatusLine();
6064 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
6065
[email protected]90499482013-06-01 00:39:506066 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:406067
6068 std::string response_data;
6069 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:016070 EXPECT_THAT(rv, IsOk());
[email protected]1b157c02009-04-21 01:55:406071 EXPECT_EQ("hello world", response_data);
6072
6073 // Empty the current queue. This is necessary because idle sockets are
6074 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:556075 base::RunLoop().RunUntilIdle();
[email protected]1b157c02009-04-21 01:55:406076
6077 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506078 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]1b157c02009-04-21 01:55:406079}
6080
[email protected]76a505b2010-08-25 06:23:006081// Make sure that we recycle a SSL socket after reading all of the response
6082// body.
bncd16676a2016-07-20 16:23:016083TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
[email protected]76a505b2010-08-25 06:23:006084 HttpRequestInfo request;
6085 request.method = "GET";
bncce36dca22015-04-21 22:11:236086 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:006087 request.load_flags = 0;
6088
6089 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:236090 MockWrite(
6091 "GET / HTTP/1.1\r\n"
6092 "Host: www.example.org\r\n"
6093 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:006094 };
6095
6096 MockRead data_reads[] = {
6097 MockRead("HTTP/1.1 200 OK\r\n"),
6098 MockRead("Content-Length: 11\r\n\r\n"),
6099 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066100 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:006101 };
6102
[email protected]8ddf8322012-02-23 18:08:066103 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076104 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:006105
6106 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6107 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:076108 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]76a505b2010-08-25 06:23:006109
[email protected]49639fa2011-12-20 23:22:416110 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:006111
danakj1fd259a02016-04-16 03:17:096112 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6113 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006115
[email protected]49639fa2011-12-20 23:22:416116 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006117
robpercival214763f2016-07-01 23:27:016118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6119 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:006120
6121 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526122 ASSERT_TRUE(response);
6123 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:006124 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6125
[email protected]90499482013-06-01 00:39:506126 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006127
6128 std::string response_data;
6129 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:016130 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:006131 EXPECT_EQ("hello world", response_data);
6132
6133 // Empty the current queue. This is necessary because idle sockets are
6134 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:556135 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006136
6137 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506138 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006139}
6140
6141// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
6142// from the pool and make sure that we recover okay.
bncd16676a2016-07-20 16:23:016143TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
[email protected]76a505b2010-08-25 06:23:006144 HttpRequestInfo request;
6145 request.method = "GET";
bncce36dca22015-04-21 22:11:236146 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:006147 request.load_flags = 0;
6148
6149 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:236150 MockWrite(
6151 "GET / HTTP/1.1\r\n"
6152 "Host: www.example.org\r\n"
6153 "Connection: keep-alive\r\n\r\n"),
6154 MockWrite(
6155 "GET / HTTP/1.1\r\n"
6156 "Host: www.example.org\r\n"
6157 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:006158 };
6159
6160 MockRead data_reads[] = {
mmenke911ee0222015-12-04 03:58:426161 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
6162 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
[email protected]76a505b2010-08-25 06:23:006163
[email protected]8ddf8322012-02-23 18:08:066164 SSLSocketDataProvider ssl(ASYNC, OK);
6165 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:076166 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6167 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
[email protected]76a505b2010-08-25 06:23:006168
6169 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6170 data_writes, arraysize(data_writes));
6171 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
6172 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:076173 session_deps_.socket_factory->AddSocketDataProvider(&data);
6174 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]76a505b2010-08-25 06:23:006175
[email protected]49639fa2011-12-20 23:22:416176 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:006177
danakj1fd259a02016-04-16 03:17:096178 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6179 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506180 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006181
[email protected]49639fa2011-12-20 23:22:416182 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006183
robpercival214763f2016-07-01 23:27:016184 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6185 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:006186
6187 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526188 ASSERT_TRUE(response);
6189 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:006190 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6191
[email protected]90499482013-06-01 00:39:506192 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006193
6194 std::string response_data;
6195 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:016196 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:006197 EXPECT_EQ("hello world", response_data);
6198
6199 // Empty the current queue. This is necessary because idle sockets are
6200 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:556201 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006202
6203 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506204 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006205
6206 // Now start the second transaction, which should reuse the previous socket.
6207
[email protected]90499482013-06-01 00:39:506208 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]76a505b2010-08-25 06:23:006209
[email protected]49639fa2011-12-20 23:22:416210 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:006211
robpercival214763f2016-07-01 23:27:016212 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6213 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]76a505b2010-08-25 06:23:006214
6215 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526216 ASSERT_TRUE(response);
6217 ASSERT_TRUE(response->headers);
[email protected]76a505b2010-08-25 06:23:006218 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6219
[email protected]90499482013-06-01 00:39:506220 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006221
6222 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:016223 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:006224 EXPECT_EQ("hello world", response_data);
6225
6226 // Empty the current queue. This is necessary because idle sockets are
6227 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:556228 base::RunLoop().RunUntilIdle();
[email protected]76a505b2010-08-25 06:23:006229
6230 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506231 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]76a505b2010-08-25 06:23:006232}
6233
maksim.sisov0adf8592016-07-15 06:25:566234// Grab a socket, use it, and put it back into the pool. Then, make
6235// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:016236TEST_F(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:566237 HttpRequestInfo request;
6238 request.method = "GET";
6239 request.url = GURL("http://www.example.org/");
6240 request.load_flags = 0;
6241
6242 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6243
6244 std::unique_ptr<HttpTransaction> trans(
6245 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6246
6247 MockRead data_reads[] = {
6248 // A part of the response body is received with the response headers.
6249 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
6250 // The rest of the response body is received in two parts.
6251 MockRead("lo"), MockRead(" world"),
6252 MockRead("junk"), // Should not be read!!
6253 MockRead(SYNCHRONOUS, OK),
6254 };
6255
6256 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6257 session_deps_.socket_factory->AddSocketDataProvider(&data);
6258
6259 TestCompletionCallback callback;
6260
6261 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6262 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6263
6264 EXPECT_THAT(callback.GetResult(rv), IsOk());
6265
6266 const HttpResponseInfo* response = trans->GetResponseInfo();
6267 ASSERT_TRUE(response);
6268 EXPECT_TRUE(response->headers);
6269 std::string status_line = response->headers->GetStatusLine();
6270 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
6271
6272 // Make memory critical notification and ensure the transaction still has been
6273 // operating right.
6274 base::MemoryPressureListener::NotifyMemoryPressure(
6275 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
6276 base::RunLoop().RunUntilIdle();
6277
6278 // Socket should not be flushed as long as it is not idle.
6279 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
6280
6281 std::string response_data;
6282 rv = ReadTransaction(trans.get(), &response_data);
6283 EXPECT_THAT(rv, IsOk());
6284 EXPECT_EQ("hello world", response_data);
6285
6286 // Empty the current queue. This is necessary because idle sockets are
6287 // added to the connection pool asynchronously with a PostTask.
6288 base::RunLoop().RunUntilIdle();
6289
6290 // We now check to make sure the socket was added back to the pool.
6291 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
6292
6293 // Idle sockets should be flushed now.
6294 base::MemoryPressureListener::NotifyMemoryPressure(
6295 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
6296 base::RunLoop().RunUntilIdle();
6297
6298 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
6299}
6300
6301// Grab an SSL socket, use it, and put it back into the pool. Then, make
6302// low memory notification and ensure the socket pool is flushed.
bncd16676a2016-07-20 16:23:016303TEST_F(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
maksim.sisov0adf8592016-07-15 06:25:566304 HttpRequestInfo request;
6305 request.method = "GET";
6306 request.url = GURL("https://www.example.org/");
6307 request.load_flags = 0;
6308
6309 MockWrite data_writes[] = {
6310 MockWrite("GET / HTTP/1.1\r\n"
6311 "Host: www.example.org\r\n"
6312 "Connection: keep-alive\r\n\r\n"),
6313 };
6314
6315 MockRead data_reads[] = {
6316 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
6317 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
6318
6319 SSLSocketDataProvider ssl(ASYNC, OK);
6320 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6321
6322 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6323 arraysize(data_writes));
6324 session_deps_.socket_factory->AddSocketDataProvider(&data);
6325
6326 TestCompletionCallback callback;
6327
6328 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6329 std::unique_ptr<HttpTransaction> trans(
6330 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6331
6332 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
6333 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6334
6335 EXPECT_THAT(callback.GetResult(rv), IsOk());
6336
6337 const HttpResponseInfo* response = trans->GetResponseInfo();
6338 ASSERT_TRUE(response);
6339 ASSERT_TRUE(response->headers);
6340 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6341
6342 // Make memory critical notification and ensure the transaction still has been
6343 // operating right.
6344 base::MemoryPressureListener::NotifyMemoryPressure(
6345 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
6346 base::RunLoop().RunUntilIdle();
6347
6348 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
6349
6350 std::string response_data;
6351 rv = ReadTransaction(trans.get(), &response_data);
6352 EXPECT_THAT(rv, IsOk());
6353 EXPECT_EQ("hello world", response_data);
6354
6355 // Empty the current queue. This is necessary because idle sockets are
6356 // added to the connection pool asynchronously with a PostTask.
6357 base::RunLoop().RunUntilIdle();
6358
6359 // We now check to make sure the socket was added back to the pool.
6360 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
6361
6362 // Make memory notification once again and ensure idle socket is closed.
6363 base::MemoryPressureListener::NotifyMemoryPressure(
6364 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
6365 base::RunLoop().RunUntilIdle();
6366
6367 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
6368}
6369
[email protected]b4404c02009-04-10 16:38:526370// Make sure that we recycle a socket after a zero-length response.
6371// http://crbug.com/9880
bncd16676a2016-07-20 16:23:016372TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:426373 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:526374 request.method = "GET";
bncce36dca22015-04-21 22:11:236375 request.url = GURL(
6376 "http://www.example.org/csi?v=3&s=web&action=&"
6377 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
6378 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
6379 "rt=prt.2642,ol.2649,xjs.2951");
[email protected]b4404c02009-04-10 16:38:526380 request.load_flags = 0;
6381
danakj1fd259a02016-04-16 03:17:096382 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]cb9bf6ca2011-01-28 13:15:276383
[email protected]b4404c02009-04-10 16:38:526384 MockRead data_reads[] = {
6385 MockRead("HTTP/1.1 204 No Content\r\n"
6386 "Content-Length: 0\r\n"
6387 "Content-Type: text/html\r\n\r\n"),
6388 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:066389 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:526390 };
6391
[email protected]31a2bfe2010-02-09 08:03:396392 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:076393 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:526394
mmenkecc2298e2015-12-07 18:20:186395 // Transaction must be created after the MockReads, so it's destroyed before
6396 // them.
danakj1fd259a02016-04-16 03:17:096397 std::unique_ptr<HttpTransaction> trans(
mmenkecc2298e2015-12-07 18:20:186398 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6399
[email protected]49639fa2011-12-20 23:22:416400 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:526401
[email protected]49639fa2011-12-20 23:22:416402 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016403 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]b4404c02009-04-10 16:38:526404
6405 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016406 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:526407
[email protected]1c773ea12009-04-28 19:58:426408 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526409 ASSERT_TRUE(response);
[email protected]b4404c02009-04-10 16:38:526410
wezca1070932016-05-26 20:30:526411 EXPECT_TRUE(response->headers);
[email protected]b4404c02009-04-10 16:38:526412 std::string status_line = response->headers->GetStatusLine();
6413 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
6414
[email protected]90499482013-06-01 00:39:506415 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526416
6417 std::string response_data;
6418 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:016419 EXPECT_THAT(rv, IsOk());
[email protected]b4404c02009-04-10 16:38:526420 EXPECT_EQ("", response_data);
6421
6422 // Empty the current queue. This is necessary because idle sockets are
6423 // added to the connection pool asynchronously with a PostTask.
fdoray92e35a72016-06-10 15:54:556424 base::RunLoop().RunUntilIdle();
[email protected]b4404c02009-04-10 16:38:526425
6426 // We now check to make sure the socket was added back to the pool.
[email protected]90499482013-06-01 00:39:506427 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]b4404c02009-04-10 16:38:526428}
6429
bncd16676a2016-07-20 16:23:016430TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
danakj1fd259a02016-04-16 03:17:096431 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:226432 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:096433 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:226434 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:276435
[email protected]1c773ea12009-04-28 19:58:426436 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:516437 // Transaction 1: a GET request that succeeds. The socket is recycled
6438 // after use.
6439 request[0].method = "GET";
6440 request[0].url = GURL("http://www.google.com/");
6441 request[0].load_flags = 0;
6442 // Transaction 2: a POST request. Reuses the socket kept alive from
6443 // transaction 1. The first attempts fails when writing the POST data.
6444 // This causes the transaction to retry with a new socket. The second
6445 // attempt succeeds.
6446 request[1].method = "POST";
6447 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]329b68b2012-11-14 17:54:276448 request[1].upload_data_stream = &upload_data_stream;
[email protected]372d34a2008-11-05 21:30:516449 request[1].load_flags = 0;
6450
danakj1fd259a02016-04-16 03:17:096451 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]372d34a2008-11-05 21:30:516452
6453 // The first socket is used for transaction 1 and the first attempt of
6454 // transaction 2.
6455
6456 // The response of transaction 1.
6457 MockRead data_reads1[] = {
6458 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
6459 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066460 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516461 };
6462 // The mock write results of transaction 1 and the first attempt of
6463 // transaction 2.
6464 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:066465 MockWrite(SYNCHRONOUS, 64), // GET
6466 MockWrite(SYNCHRONOUS, 93), // POST
6467 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:516468 };
[email protected]31a2bfe2010-02-09 08:03:396469 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6470 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:516471
6472 // The second socket is used for the second attempt of transaction 2.
6473
6474 // The response of transaction 2.
6475 MockRead data_reads2[] = {
6476 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
6477 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:066478 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:516479 };
6480 // The mock write results of the second attempt of transaction 2.
6481 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:066482 MockWrite(SYNCHRONOUS, 93), // POST
6483 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:516484 };
[email protected]31a2bfe2010-02-09 08:03:396485 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6486 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:516487
[email protected]bb88e1d32013-05-03 23:11:076488 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6489 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:516490
thestig9d3bb0c2015-01-24 00:49:516491 const char* const kExpectedResponseData[] = {
[email protected]372d34a2008-11-05 21:30:516492 "hello world", "welcome"
6493 };
6494
6495 for (int i = 0; i < 2; ++i) {
danakj1fd259a02016-04-16 03:17:096496 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506497 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]372d34a2008-11-05 21:30:516498
[email protected]49639fa2011-12-20 23:22:416499 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:516500
[email protected]49639fa2011-12-20 23:22:416501 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016502 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]372d34a2008-11-05 21:30:516503
6504 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:016505 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:516506
[email protected]1c773ea12009-04-28 19:58:426507 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526508 ASSERT_TRUE(response);
[email protected]372d34a2008-11-05 21:30:516509
wezca1070932016-05-26 20:30:526510 EXPECT_TRUE(response->headers);
[email protected]372d34a2008-11-05 21:30:516511 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6512
6513 std::string response_data;
6514 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:016515 EXPECT_THAT(rv, IsOk());
[email protected]372d34a2008-11-05 21:30:516516 EXPECT_EQ(kExpectedResponseData[i], response_data);
6517 }
6518}
[email protected]f9ee6b52008-11-08 06:46:236519
6520// Test the request-challenge-retry sequence for basic auth when there is
6521// an identity in the URL. The request should be sent as normal, but when
[email protected]2262e3a2012-05-22 16:08:166522// it fails the identity from the URL is used to answer the challenge.
bncd16676a2016-07-20 16:23:016523TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:426524 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236525 request.method = "GET";
bncce36dca22015-04-21 22:11:236526 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:416527 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:296528
danakj1fd259a02016-04-16 03:17:096529 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6530 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416531 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276532
[email protected]a97cca42009-08-14 01:00:296533 // The password contains an escaped character -- for this test to pass it
6534 // will need to be unescaped by HttpNetworkTransaction.
6535 EXPECT_EQ("b%40r", request.url.password());
6536
[email protected]f9ee6b52008-11-08 06:46:236537 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236538 MockWrite(
6539 "GET / HTTP/1.1\r\n"
6540 "Host: www.example.org\r\n"
6541 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236542 };
6543
6544 MockRead data_reads1[] = {
6545 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6546 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6547 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066548 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236549 };
6550
[email protected]2262e3a2012-05-22 16:08:166551 // After the challenge above, the transaction will be restarted using the
6552 // identity from the url (foo, b@r) to answer the challenge.
6553 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236554 MockWrite(
6555 "GET / HTTP/1.1\r\n"
6556 "Host: www.example.org\r\n"
6557 "Connection: keep-alive\r\n"
6558 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166559 };
6560
6561 MockRead data_reads2[] = {
6562 MockRead("HTTP/1.0 200 OK\r\n"),
6563 MockRead("Content-Length: 100\r\n\r\n"),
6564 MockRead(SYNCHRONOUS, OK),
6565 };
6566
[email protected]31a2bfe2010-02-09 08:03:396567 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6568 data_writes1, arraysize(data_writes1));
[email protected]2262e3a2012-05-22 16:08:166569 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6570 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076571 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6572 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236573
[email protected]49639fa2011-12-20 23:22:416574 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:416575 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016576 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:236577 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016578 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:166579 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6580
6581 TestCompletionCallback callback2;
6582 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:016583 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:166584 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016585 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:226586 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6587
[email protected]2262e3a2012-05-22 16:08:166588 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526589 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:166590
6591 // There is no challenge info, since the identity in URL worked.
wezca1070932016-05-26 20:30:526592 EXPECT_FALSE(response->auth_challenge);
[email protected]2262e3a2012-05-22 16:08:166593
6594 EXPECT_EQ(100, response->headers->GetContentLength());
6595
6596 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:556597 base::RunLoop().RunUntilIdle();
[email protected]2262e3a2012-05-22 16:08:166598}
6599
6600// Test the request-challenge-retry sequence for basic auth when there is an
6601// incorrect identity in the URL. The identity from the URL should be used only
6602// once.
bncd16676a2016-07-20 16:23:016603TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]2262e3a2012-05-22 16:08:166604 HttpRequestInfo request;
6605 request.method = "GET";
6606 // Note: the URL has a username:password in it. The password "baz" is
6607 // wrong (should be "bar").
bncce36dca22015-04-21 22:11:236608 request.url = GURL("http://foo:[email protected]/");
[email protected]2262e3a2012-05-22 16:08:166609
6610 request.load_flags = LOAD_NORMAL;
6611
danakj1fd259a02016-04-16 03:17:096612 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6613 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416614 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2262e3a2012-05-22 16:08:166615
6616 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236617 MockWrite(
6618 "GET / HTTP/1.1\r\n"
6619 "Host: www.example.org\r\n"
6620 "Connection: keep-alive\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166621 };
6622
6623 MockRead data_reads1[] = {
6624 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6625 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6626 MockRead("Content-Length: 10\r\n\r\n"),
6627 MockRead(SYNCHRONOUS, ERR_FAILED),
6628 };
6629
6630 // After the challenge above, the transaction will be restarted using the
6631 // identity from the url (foo, baz) to answer the challenge.
6632 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236633 MockWrite(
6634 "GET / HTTP/1.1\r\n"
6635 "Host: www.example.org\r\n"
6636 "Connection: keep-alive\r\n"
6637 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166638 };
6639
6640 MockRead data_reads2[] = {
6641 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6642 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6643 MockRead("Content-Length: 10\r\n\r\n"),
6644 MockRead(SYNCHRONOUS, ERR_FAILED),
6645 };
6646
6647 // After the challenge above, the transaction will be restarted using the
6648 // identity supplied by the user (foo, bar) to answer the challenge.
6649 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236650 MockWrite(
6651 "GET / HTTP/1.1\r\n"
6652 "Host: www.example.org\r\n"
6653 "Connection: keep-alive\r\n"
6654 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2262e3a2012-05-22 16:08:166655 };
6656
6657 MockRead data_reads3[] = {
6658 MockRead("HTTP/1.0 200 OK\r\n"),
6659 MockRead("Content-Length: 100\r\n\r\n"),
6660 MockRead(SYNCHRONOUS, OK),
6661 };
6662
6663 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6664 data_writes1, arraysize(data_writes1));
6665 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6666 data_writes2, arraysize(data_writes2));
6667 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6668 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:076669 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6670 session_deps_.socket_factory->AddSocketDataProvider(&data2);
6671 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]2262e3a2012-05-22 16:08:166672
6673 TestCompletionCallback callback1;
6674
6675 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016676 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:166677
6678 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016679 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:166680
6681 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
6682 TestCompletionCallback callback2;
6683 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:016684 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:166685 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016686 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:166687 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6688
6689 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526690 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:166691 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6692
6693 TestCompletionCallback callback3;
6694 rv = trans->RestartWithAuth(
6695 AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:016696 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2262e3a2012-05-22 16:08:166697 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:016698 EXPECT_THAT(rv, IsOk());
[email protected]2262e3a2012-05-22 16:08:166699 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6700
6701 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526702 ASSERT_TRUE(response);
[email protected]2262e3a2012-05-22 16:08:166703
6704 // There is no challenge info, since the identity worked.
wezca1070932016-05-26 20:30:526705 EXPECT_FALSE(response->auth_challenge);
[email protected]2262e3a2012-05-22 16:08:166706
6707 EXPECT_EQ(100, response->headers->GetContentLength());
6708
[email protected]ea9dc9a2009-09-05 00:43:326709 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:556710 base::RunLoop().RunUntilIdle();
[email protected]ea9dc9a2009-09-05 00:43:326711}
6712
[email protected]2217aa22013-10-11 03:03:546713
6714// Test the request-challenge-retry sequence for basic auth when there is a
6715// correct identity in the URL, but its use is being suppressed. The identity
6716// from the URL should never be used.
bncd16676a2016-07-20 16:23:016717TEST_F(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
[email protected]2217aa22013-10-11 03:03:546718 HttpRequestInfo request;
6719 request.method = "GET";
bncce36dca22015-04-21 22:11:236720 request.url = GURL("http://foo:[email protected]/");
[email protected]2217aa22013-10-11 03:03:546721 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
6722
danakj1fd259a02016-04-16 03:17:096723 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6724 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:416725 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2217aa22013-10-11 03:03:546726
6727 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236728 MockWrite(
6729 "GET / HTTP/1.1\r\n"
6730 "Host: www.example.org\r\n"
6731 "Connection: keep-alive\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546732 };
6733
6734 MockRead data_reads1[] = {
6735 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6736 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6737 MockRead("Content-Length: 10\r\n\r\n"),
6738 MockRead(SYNCHRONOUS, ERR_FAILED),
6739 };
6740
6741 // After the challenge above, the transaction will be restarted using the
6742 // identity supplied by the user, not the one in the URL, to answer the
6743 // challenge.
6744 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:236745 MockWrite(
6746 "GET / HTTP/1.1\r\n"
6747 "Host: www.example.org\r\n"
6748 "Connection: keep-alive\r\n"
6749 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]2217aa22013-10-11 03:03:546750 };
6751
6752 MockRead data_reads3[] = {
6753 MockRead("HTTP/1.0 200 OK\r\n"),
6754 MockRead("Content-Length: 100\r\n\r\n"),
6755 MockRead(SYNCHRONOUS, OK),
6756 };
6757
6758 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6759 data_writes1, arraysize(data_writes1));
6760 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6761 data_writes3, arraysize(data_writes3));
6762 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6763 session_deps_.socket_factory->AddSocketDataProvider(&data3);
6764
6765 TestCompletionCallback callback1;
6766 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016767 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:546768 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016769 EXPECT_THAT(rv, IsOk());
[email protected]2217aa22013-10-11 03:03:546770 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6771
6772 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526773 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:546774 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
6775
6776 TestCompletionCallback callback3;
6777 rv = trans->RestartWithAuth(
6778 AuthCredentials(kFoo, kBar), callback3.callback());
robpercival214763f2016-07-01 23:27:016779 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2217aa22013-10-11 03:03:546780 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:016781 EXPECT_THAT(rv, IsOk());
[email protected]2217aa22013-10-11 03:03:546782 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
6783
6784 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526785 ASSERT_TRUE(response);
[email protected]2217aa22013-10-11 03:03:546786
6787 // There is no challenge info, since the identity worked.
wezca1070932016-05-26 20:30:526788 EXPECT_FALSE(response->auth_challenge);
[email protected]2217aa22013-10-11 03:03:546789 EXPECT_EQ(100, response->headers->GetContentLength());
6790
6791 // Empty the current queue.
fdoray92e35a72016-06-10 15:54:556792 base::RunLoop().RunUntilIdle();
[email protected]2217aa22013-10-11 03:03:546793}
6794
[email protected]f9ee6b52008-11-08 06:46:236795// Test that previously tried username/passwords for a realm get re-used.
bncd16676a2016-07-20 16:23:016796TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
danakj1fd259a02016-04-16 03:17:096797 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]f9ee6b52008-11-08 06:46:236798
6799 // Transaction 1: authenticate (foo, bar) on MyRealm1
6800 {
[email protected]1c773ea12009-04-28 19:58:426801 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236802 request.method = "GET";
bncce36dca22015-04-21 22:11:236803 request.url = GURL("http://www.example.org/x/y/z");
[email protected]f9ee6b52008-11-08 06:46:236804 request.load_flags = 0;
6805
danakj1fd259a02016-04-16 03:17:096806 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506807 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276808
[email protected]f9ee6b52008-11-08 06:46:236809 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236810 MockWrite(
6811 "GET /x/y/z HTTP/1.1\r\n"
6812 "Host: www.example.org\r\n"
6813 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236814 };
6815
6816 MockRead data_reads1[] = {
6817 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6818 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6819 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066820 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236821 };
6822
6823 // Resend with authorization (username=foo, password=bar)
6824 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236825 MockWrite(
6826 "GET /x/y/z HTTP/1.1\r\n"
6827 "Host: www.example.org\r\n"
6828 "Connection: keep-alive\r\n"
6829 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236830 };
6831
6832 // Sever accepts the authorization.
6833 MockRead data_reads2[] = {
6834 MockRead("HTTP/1.0 200 OK\r\n"),
6835 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066836 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236837 };
6838
[email protected]31a2bfe2010-02-09 08:03:396839 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6840 data_writes1, arraysize(data_writes1));
6841 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6842 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076843 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6844 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236845
[email protected]49639fa2011-12-20 23:22:416846 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236847
[email protected]49639fa2011-12-20 23:22:416848 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016849 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:236850
6851 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016852 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:236853
[email protected]1c773ea12009-04-28 19:58:426854 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526855 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:046856 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:236857
[email protected]49639fa2011-12-20 23:22:416858 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236859
[email protected]49639fa2011-12-20 23:22:416860 rv = trans->RestartWithAuth(
6861 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:016862 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:236863
6864 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016865 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:236866
6867 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526868 ASSERT_TRUE(response);
6869 EXPECT_FALSE(response->auth_challenge);
[email protected]f9ee6b52008-11-08 06:46:236870 EXPECT_EQ(100, response->headers->GetContentLength());
6871 }
6872
6873 // ------------------------------------------------------------------------
6874
6875 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
6876 {
[email protected]1c773ea12009-04-28 19:58:426877 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236878 request.method = "GET";
6879 // Note that Transaction 1 was at /x/y/z, so this is in the same
6880 // protection space as MyRealm1.
bncce36dca22015-04-21 22:11:236881 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]f9ee6b52008-11-08 06:46:236882 request.load_flags = 0;
6883
danakj1fd259a02016-04-16 03:17:096884 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506885 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276886
[email protected]f9ee6b52008-11-08 06:46:236887 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236888 MockWrite(
6889 "GET /x/y/a/b HTTP/1.1\r\n"
6890 "Host: www.example.org\r\n"
6891 "Connection: keep-alive\r\n"
6892 // Send preemptive authorization for MyRealm1
6893 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236894 };
6895
6896 // The server didn't like the preemptive authorization, and
6897 // challenges us for a different realm (MyRealm2).
6898 MockRead data_reads1[] = {
6899 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6900 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
6901 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066902 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:236903 };
6904
6905 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
6906 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:236907 MockWrite(
6908 "GET /x/y/a/b HTTP/1.1\r\n"
6909 "Host: www.example.org\r\n"
6910 "Connection: keep-alive\r\n"
6911 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236912 };
6913
6914 // Sever accepts the authorization.
6915 MockRead data_reads2[] = {
6916 MockRead("HTTP/1.0 200 OK\r\n"),
6917 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066918 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236919 };
6920
[email protected]31a2bfe2010-02-09 08:03:396921 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6922 data_writes1, arraysize(data_writes1));
6923 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6924 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:076925 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6926 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:236927
[email protected]49639fa2011-12-20 23:22:416928 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236929
[email protected]49639fa2011-12-20 23:22:416930 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016931 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:236932
6933 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:016934 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:236935
[email protected]1c773ea12009-04-28 19:58:426936 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526937 ASSERT_TRUE(response);
6938 ASSERT_TRUE(response->auth_challenge);
[email protected]79cb5c12011-09-12 13:12:046939 EXPECT_FALSE(response->auth_challenge->is_proxy);
asanka098c0092016-06-16 20:18:436940 EXPECT_EQ("http://www.example.org",
6941 response->auth_challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:046942 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
aberentbba302d2015-12-03 10:20:196943 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:236944
[email protected]49639fa2011-12-20 23:22:416945 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:236946
[email protected]49639fa2011-12-20 23:22:416947 rv = trans->RestartWithAuth(
6948 AuthCredentials(kFoo2, kBar2), callback2.callback());
robpercival214763f2016-07-01 23:27:016949 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:236950
6951 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:016952 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:236953
6954 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:526955 ASSERT_TRUE(response);
6956 EXPECT_FALSE(response->auth_challenge);
[email protected]f9ee6b52008-11-08 06:46:236957 EXPECT_EQ(100, response->headers->GetContentLength());
6958 }
6959
6960 // ------------------------------------------------------------------------
6961
6962 // Transaction 3: Resend a request in MyRealm's protection space --
6963 // succeed with preemptive authorization.
6964 {
[email protected]1c773ea12009-04-28 19:58:426965 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:236966 request.method = "GET";
bncce36dca22015-04-21 22:11:236967 request.url = GURL("http://www.example.org/x/y/z2");
[email protected]f9ee6b52008-11-08 06:46:236968 request.load_flags = 0;
6969
danakj1fd259a02016-04-16 03:17:096970 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:506971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:276972
[email protected]f9ee6b52008-11-08 06:46:236973 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:236974 MockWrite(
6975 "GET /x/y/z2 HTTP/1.1\r\n"
6976 "Host: www.example.org\r\n"
6977 "Connection: keep-alive\r\n"
6978 // The authorization for MyRealm1 gets sent preemptively
6979 // (since the url is in the same protection space)
6980 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:236981 };
6982
6983 // Sever accepts the preemptive authorization
6984 MockRead data_reads1[] = {
6985 MockRead("HTTP/1.0 200 OK\r\n"),
6986 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066987 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:236988 };
6989
[email protected]31a2bfe2010-02-09 08:03:396990 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6991 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:076992 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:236993
[email protected]49639fa2011-12-20 23:22:416994 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:236995
[email protected]49639fa2011-12-20 23:22:416996 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:016997 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:236998
6999 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017000 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:237001
[email protected]1c773ea12009-04-28 19:58:427002 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527003 ASSERT_TRUE(response);
[email protected]f9ee6b52008-11-08 06:46:237004
wezca1070932016-05-26 20:30:527005 EXPECT_FALSE(response->auth_challenge);
[email protected]f9ee6b52008-11-08 06:46:237006 EXPECT_EQ(100, response->headers->GetContentLength());
7007 }
7008
7009 // ------------------------------------------------------------------------
7010
7011 // Transaction 4: request another URL in MyRealm (however the
7012 // url is not known to belong to the protection space, so no pre-auth).
7013 {
[email protected]1c773ea12009-04-28 19:58:427014 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:237015 request.method = "GET";
bncce36dca22015-04-21 22:11:237016 request.url = GURL("http://www.example.org/x/1");
[email protected]f9ee6b52008-11-08 06:46:237017 request.load_flags = 0;
7018
danakj1fd259a02016-04-16 03:17:097019 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507020 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277021
[email protected]f9ee6b52008-11-08 06:46:237022 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237023 MockWrite(
7024 "GET /x/1 HTTP/1.1\r\n"
7025 "Host: www.example.org\r\n"
7026 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237027 };
7028
7029 MockRead data_reads1[] = {
7030 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7031 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7032 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067033 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:237034 };
7035
7036 // Resend with authorization from MyRealm's cache.
7037 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237038 MockWrite(
7039 "GET /x/1 HTTP/1.1\r\n"
7040 "Host: www.example.org\r\n"
7041 "Connection: keep-alive\r\n"
7042 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237043 };
7044
7045 // Sever accepts the authorization.
7046 MockRead data_reads2[] = {
7047 MockRead("HTTP/1.0 200 OK\r\n"),
7048 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067049 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:237050 };
7051
[email protected]31a2bfe2010-02-09 08:03:397052 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7053 data_writes1, arraysize(data_writes1));
7054 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7055 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:077056 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7057 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:237058
[email protected]49639fa2011-12-20 23:22:417059 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:237060
[email protected]49639fa2011-12-20 23:22:417061 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017062 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:237063
7064 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017065 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:237066
[email protected]0757e7702009-03-27 04:00:227067 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417068 TestCompletionCallback callback2;
7069 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:017070 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227071 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017072 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227073 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
7074
[email protected]1c773ea12009-04-28 19:58:427075 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527076 ASSERT_TRUE(response);
7077 EXPECT_FALSE(response->auth_challenge);
[email protected]f9ee6b52008-11-08 06:46:237078 EXPECT_EQ(100, response->headers->GetContentLength());
7079 }
7080
7081 // ------------------------------------------------------------------------
7082
7083 // Transaction 5: request a URL in MyRealm, but the server rejects the
7084 // cached identity. Should invalidate and re-prompt.
7085 {
[email protected]1c773ea12009-04-28 19:58:427086 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:237087 request.method = "GET";
bncce36dca22015-04-21 22:11:237088 request.url = GURL("http://www.example.org/p/q/t");
[email protected]f9ee6b52008-11-08 06:46:237089 request.load_flags = 0;
7090
danakj1fd259a02016-04-16 03:17:097091 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507092 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277093
[email protected]f9ee6b52008-11-08 06:46:237094 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237095 MockWrite(
7096 "GET /p/q/t HTTP/1.1\r\n"
7097 "Host: www.example.org\r\n"
7098 "Connection: keep-alive\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237099 };
7100
7101 MockRead data_reads1[] = {
7102 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7103 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7104 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067105 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:237106 };
7107
7108 // Resend with authorization from cache for MyRealm.
7109 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237110 MockWrite(
7111 "GET /p/q/t HTTP/1.1\r\n"
7112 "Host: www.example.org\r\n"
7113 "Connection: keep-alive\r\n"
7114 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237115 };
7116
7117 // Sever rejects the authorization.
7118 MockRead data_reads2[] = {
7119 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7120 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7121 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067122 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:237123 };
7124
7125 // At this point we should prompt for new credentials for MyRealm.
7126 // Restart with username=foo3, password=foo4.
7127 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:237128 MockWrite(
7129 "GET /p/q/t HTTP/1.1\r\n"
7130 "Host: www.example.org\r\n"
7131 "Connection: keep-alive\r\n"
7132 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:237133 };
7134
7135 // Sever accepts the authorization.
7136 MockRead data_reads3[] = {
7137 MockRead("HTTP/1.0 200 OK\r\n"),
7138 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067139 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:237140 };
7141
[email protected]31a2bfe2010-02-09 08:03:397142 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7143 data_writes1, arraysize(data_writes1));
7144 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7145 data_writes2, arraysize(data_writes2));
7146 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
7147 data_writes3, arraysize(data_writes3));
[email protected]bb88e1d32013-05-03 23:11:077148 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7149 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7150 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:237151
[email protected]49639fa2011-12-20 23:22:417152 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:237153
[email protected]49639fa2011-12-20 23:22:417154 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017155 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:237156
7157 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017158 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:237159
[email protected]0757e7702009-03-27 04:00:227160 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:417161 TestCompletionCallback callback2;
7162 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
robpercival214763f2016-07-01 23:27:017163 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0757e7702009-03-27 04:00:227164 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017165 EXPECT_THAT(rv, IsOk());
[email protected]0757e7702009-03-27 04:00:227166 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
7167
[email protected]1c773ea12009-04-28 19:58:427168 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527169 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:047170 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:237171
[email protected]49639fa2011-12-20 23:22:417172 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:237173
[email protected]49639fa2011-12-20 23:22:417174 rv = trans->RestartWithAuth(
7175 AuthCredentials(kFoo3, kBar3), callback3.callback());
robpercival214763f2016-07-01 23:27:017176 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]f9ee6b52008-11-08 06:46:237177
[email protected]0757e7702009-03-27 04:00:227178 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:017179 EXPECT_THAT(rv, IsOk());
[email protected]f9ee6b52008-11-08 06:46:237180
7181 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527182 ASSERT_TRUE(response);
7183 EXPECT_FALSE(response->auth_challenge);
[email protected]f9ee6b52008-11-08 06:46:237184 EXPECT_EQ(100, response->headers->GetContentLength());
7185 }
7186}
[email protected]89ceba9a2009-03-21 03:46:067187
[email protected]3c32c5f2010-05-18 15:18:127188// Tests that nonce count increments when multiple auth attempts
7189// are started with the same nonce.
bncd16676a2016-07-20 16:23:017190TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
[email protected]54fea2562010-11-17 14:40:447191 HttpAuthHandlerDigest::Factory* digest_factory =
7192 new HttpAuthHandlerDigest::Factory();
7193 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
7194 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
7195 digest_factory->set_nonce_generator(nonce_generator);
[email protected]bb88e1d32013-05-03 23:11:077196 session_deps_.http_auth_handler_factory.reset(digest_factory);
danakj1fd259a02016-04-16 03:17:097197 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3c32c5f2010-05-18 15:18:127198
7199 // Transaction 1: authenticate (foo, bar) on MyRealm1
7200 {
[email protected]3c32c5f2010-05-18 15:18:127201 HttpRequestInfo request;
7202 request.method = "GET";
bncce36dca22015-04-21 22:11:237203 request.url = GURL("http://www.example.org/x/y/z");
[email protected]3c32c5f2010-05-18 15:18:127204 request.load_flags = 0;
7205
danakj1fd259a02016-04-16 03:17:097206 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507207 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277208
[email protected]3c32c5f2010-05-18 15:18:127209 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237210 MockWrite(
7211 "GET /x/y/z HTTP/1.1\r\n"
7212 "Host: www.example.org\r\n"
7213 "Connection: keep-alive\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:127214 };
7215
7216 MockRead data_reads1[] = {
7217 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
7218 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
7219 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067220 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:127221 };
7222
7223 // Resend with authorization (username=foo, password=bar)
7224 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:237225 MockWrite(
7226 "GET /x/y/z HTTP/1.1\r\n"
7227 "Host: www.example.org\r\n"
7228 "Connection: keep-alive\r\n"
7229 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
7230 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
7231 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
7232 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:127233 };
7234
7235 // Sever accepts the authorization.
7236 MockRead data_reads2[] = {
zmo9528c9f42015-08-04 22:12:087237 MockRead("HTTP/1.0 200 OK\r\n"),
7238 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:127239 };
7240
7241 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7242 data_writes1, arraysize(data_writes1));
7243 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7244 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:077245 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7246 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]3c32c5f2010-05-18 15:18:127247
[email protected]49639fa2011-12-20 23:22:417248 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:127249
[email protected]49639fa2011-12-20 23:22:417250 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017251 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:127252
7253 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017254 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:127255
7256 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527257 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:047258 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:127259
[email protected]49639fa2011-12-20 23:22:417260 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:127261
[email protected]49639fa2011-12-20 23:22:417262 rv = trans->RestartWithAuth(
7263 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:017264 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:127265
7266 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017267 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:127268
7269 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527270 ASSERT_TRUE(response);
7271 EXPECT_FALSE(response->auth_challenge);
[email protected]3c32c5f2010-05-18 15:18:127272 }
7273
7274 // ------------------------------------------------------------------------
7275
7276 // Transaction 2: Request another resource in digestive's protection space.
7277 // This will preemptively add an Authorization header which should have an
7278 // "nc" value of 2 (as compared to 1 in the first use.
7279 {
[email protected]3c32c5f2010-05-18 15:18:127280 HttpRequestInfo request;
7281 request.method = "GET";
7282 // Note that Transaction 1 was at /x/y/z, so this is in the same
7283 // protection space as digest.
bncce36dca22015-04-21 22:11:237284 request.url = GURL("http://www.example.org/x/y/a/b");
[email protected]3c32c5f2010-05-18 15:18:127285 request.load_flags = 0;
7286
danakj1fd259a02016-04-16 03:17:097287 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507288 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277289
[email protected]3c32c5f2010-05-18 15:18:127290 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:237291 MockWrite(
7292 "GET /x/y/a/b HTTP/1.1\r\n"
7293 "Host: www.example.org\r\n"
7294 "Connection: keep-alive\r\n"
7295 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
7296 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
7297 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
7298 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
[email protected]3c32c5f2010-05-18 15:18:127299 };
7300
7301 // Sever accepts the authorization.
7302 MockRead data_reads1[] = {
7303 MockRead("HTTP/1.0 200 OK\r\n"),
7304 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067305 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:127306 };
7307
7308 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7309 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:077310 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]3c32c5f2010-05-18 15:18:127311
[email protected]49639fa2011-12-20 23:22:417312 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:127313
[email protected]49639fa2011-12-20 23:22:417314 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017315 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3c32c5f2010-05-18 15:18:127316
7317 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017318 EXPECT_THAT(rv, IsOk());
[email protected]3c32c5f2010-05-18 15:18:127319
7320 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527321 ASSERT_TRUE(response);
7322 EXPECT_FALSE(response->auth_challenge);
[email protected]3c32c5f2010-05-18 15:18:127323 }
7324}
7325
[email protected]89ceba9a2009-03-21 03:46:067326// Test the ResetStateForRestart() private method.
bncd16676a2016-07-20 16:23:017327TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
[email protected]89ceba9a2009-03-21 03:46:067328 // Create a transaction (the dependencies aren't important).
danakj1fd259a02016-04-16 03:17:097329 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7330 std::unique_ptr<HttpNetworkTransaction> trans(
dcheng48459ac22014-08-26 00:46:417331 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]89ceba9a2009-03-21 03:46:067332
7333 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:067334 trans->read_buf_ = new IOBuffer(15);
7335 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:207336 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:067337
7338 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:147339 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:577340 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:087341 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:577342 response->response_time = base::Time::Now();
7343 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:067344
7345 { // Setup state for response_.vary_data
7346 HttpRequestInfo request;
7347 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
7348 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:277349 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:437350 request.extra_headers.SetHeader("Foo", "1");
7351 request.extra_headers.SetHeader("bar", "23");
[email protected]90499482013-06-01 00:39:507352 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
[email protected]89ceba9a2009-03-21 03:46:067353 }
7354
7355 // Cause the above state to be reset.
7356 trans->ResetStateForRestart();
7357
7358 // Verify that the state that needed to be reset, has been reset.
wezca1070932016-05-26 20:30:527359 EXPECT_FALSE(trans->read_buf_);
[email protected]89ceba9a2009-03-21 03:46:067360 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:207361 EXPECT_TRUE(trans->request_headers_.IsEmpty());
wezca1070932016-05-26 20:30:527362 EXPECT_FALSE(response->auth_challenge);
7363 EXPECT_FALSE(response->headers);
[email protected]34f40942010-10-04 00:34:047364 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:087365 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:577366 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:067367}
7368
[email protected]bacff652009-03-31 17:50:337369// Test HTTPS connections to a site with a bad certificate
bncd16676a2016-07-20 16:23:017370TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:337371 HttpRequestInfo request;
7372 request.method = "GET";
bncce36dca22015-04-21 22:11:237373 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337374 request.load_flags = 0;
7375
danakj1fd259a02016-04-16 03:17:097376 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7377 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417378 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:277379
[email protected]bacff652009-03-31 17:50:337380 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:237381 MockWrite(
7382 "GET / HTTP/1.1\r\n"
7383 "Host: www.example.org\r\n"
7384 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337385 };
7386
7387 MockRead data_reads[] = {
7388 MockRead("HTTP/1.0 200 OK\r\n"),
7389 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7390 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067391 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337392 };
7393
[email protected]5ecc992a42009-11-11 01:41:597394 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:397395 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7396 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067397 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7398 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337399
[email protected]bb88e1d32013-05-03 23:11:077400 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7401 session_deps_.socket_factory->AddSocketDataProvider(&data);
7402 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337404
[email protected]49639fa2011-12-20 23:22:417405 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337406
[email protected]49639fa2011-12-20 23:22:417407 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017408 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:337409
7410 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017411 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:337412
[email protected]49639fa2011-12-20 23:22:417413 rv = trans->RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:017414 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:337415
7416 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017417 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:337418
7419 const HttpResponseInfo* response = trans->GetResponseInfo();
7420
wezca1070932016-05-26 20:30:527421 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:337422 EXPECT_EQ(100, response->headers->GetContentLength());
7423}
7424
7425// Test HTTPS connections to a site with a bad certificate, going through a
7426// proxy
bncd16676a2016-07-20 16:23:017427TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
rdsmith82957ad2015-09-16 19:42:037428 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]bacff652009-03-31 17:50:337429
7430 HttpRequestInfo request;
7431 request.method = "GET";
bncce36dca22015-04-21 22:11:237432 request.url = GURL("https://www.example.org/");
[email protected]bacff652009-03-31 17:50:337433 request.load_flags = 0;
7434
7435 MockWrite proxy_writes[] = {
rsleevidb16bb02015-11-12 23:47:177436 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7437 "Host: www.example.org:443\r\n"
7438 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337439 };
7440
7441 MockRead proxy_reads[] = {
7442 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067443 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:337444 };
7445
7446 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177447 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7448 "Host: www.example.org:443\r\n"
7449 "Proxy-Connection: keep-alive\r\n\r\n"),
7450 MockWrite("GET / HTTP/1.1\r\n"
7451 "Host: www.example.org\r\n"
7452 "Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:337453 };
7454
7455 MockRead data_reads[] = {
7456 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7457 MockRead("HTTP/1.0 200 OK\r\n"),
7458 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7459 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067460 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:337461 };
7462
[email protected]31a2bfe2010-02-09 08:03:397463 StaticSocketDataProvider ssl_bad_certificate(
7464 proxy_reads, arraysize(proxy_reads),
7465 proxy_writes, arraysize(proxy_writes));
7466 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7467 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067468 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
7469 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:337470
[email protected]bb88e1d32013-05-03 23:11:077471 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
7472 session_deps_.socket_factory->AddSocketDataProvider(&data);
7473 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
7474 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:337475
[email protected]49639fa2011-12-20 23:22:417476 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:337477
7478 for (int i = 0; i < 2; i++) {
[email protected]bb88e1d32013-05-03 23:11:077479 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:337480
danakj1fd259a02016-04-16 03:17:097481 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7482 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417483 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bacff652009-03-31 17:50:337484
[email protected]49639fa2011-12-20 23:22:417485 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017486 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:337487
7488 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017489 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]bacff652009-03-31 17:50:337490
[email protected]49639fa2011-12-20 23:22:417491 rv = trans->RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:017492 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bacff652009-03-31 17:50:337493
7494 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017495 EXPECT_THAT(rv, IsOk());
[email protected]bacff652009-03-31 17:50:337496
7497 const HttpResponseInfo* response = trans->GetResponseInfo();
7498
wezca1070932016-05-26 20:30:527499 ASSERT_TRUE(response);
[email protected]bacff652009-03-31 17:50:337500 EXPECT_EQ(100, response->headers->GetContentLength());
7501 }
7502}
7503
[email protected]2df19bb2010-08-25 20:13:467504
7505// Test HTTPS connections to a site, going through an HTTPS proxy
bncd16676a2016-07-20 16:23:017506TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037507 session_deps_.proxy_service =
7508 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517509 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077510 session_deps_.net_log = &net_log;
[email protected]2df19bb2010-08-25 20:13:467511
7512 HttpRequestInfo request;
7513 request.method = "GET";
bncce36dca22015-04-21 22:11:237514 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:467515 request.load_flags = 0;
7516
7517 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177518 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7519 "Host: www.example.org:443\r\n"
7520 "Proxy-Connection: keep-alive\r\n\r\n"),
7521 MockWrite("GET / HTTP/1.1\r\n"
7522 "Host: www.example.org\r\n"
7523 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:467524 };
7525
7526 MockRead data_reads[] = {
7527 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7528 MockRead("HTTP/1.1 200 OK\r\n"),
7529 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7530 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067531 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:467532 };
7533
7534 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7535 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067536 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
7537 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:467538
[email protected]bb88e1d32013-05-03 23:11:077539 session_deps_.socket_factory->AddSocketDataProvider(&data);
7540 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
7541 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
[email protected]2df19bb2010-08-25 20:13:467542
[email protected]49639fa2011-12-20 23:22:417543 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:467544
danakj1fd259a02016-04-16 03:17:097545 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7546 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417547 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:467548
[email protected]49639fa2011-12-20 23:22:417549 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017550 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:467551
7552 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017553 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:467554 const HttpResponseInfo* response = trans->GetResponseInfo();
7555
wezca1070932016-05-26 20:30:527556 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:467557
7558 EXPECT_TRUE(response->headers->IsKeepAlive());
7559 EXPECT_EQ(200, response->headers->response_code());
7560 EXPECT_EQ(100, response->headers->GetContentLength());
7561 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:207562
7563 LoadTimingInfo load_timing_info;
7564 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7565 TestLoadTimingNotReusedWithPac(load_timing_info,
7566 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]2df19bb2010-08-25 20:13:467567}
7568
[email protected]511f6f52010-12-17 03:58:297569// Test an HTTPS Proxy's ability to redirect a CONNECT request
bncd16676a2016-07-20 16:23:017570TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037571 session_deps_.proxy_service =
7572 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:517573 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:077574 session_deps_.net_log = &net_log;
[email protected]511f6f52010-12-17 03:58:297575
7576 HttpRequestInfo request;
7577 request.method = "GET";
bncce36dca22015-04-21 22:11:237578 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297579 request.load_flags = 0;
7580
7581 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177582 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7583 "Host: www.example.org:443\r\n"
7584 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297585 };
7586
7587 MockRead data_reads[] = {
7588 MockRead("HTTP/1.1 302 Redirect\r\n"),
7589 MockRead("Location: http://login.example.com/\r\n"),
7590 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:067591 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297592 };
7593
7594 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7595 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067596 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297597
[email protected]bb88e1d32013-05-03 23:11:077598 session_deps_.socket_factory->AddSocketDataProvider(&data);
7599 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297600
[email protected]49639fa2011-12-20 23:22:417601 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297602
danakj1fd259a02016-04-16 03:17:097603 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7604 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417605 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297606
[email protected]49639fa2011-12-20 23:22:417607 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017608 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:297609
7610 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017611 EXPECT_THAT(rv, IsOk());
[email protected]511f6f52010-12-17 03:58:297612 const HttpResponseInfo* response = trans->GetResponseInfo();
7613
wezca1070932016-05-26 20:30:527614 ASSERT_TRUE(response);
[email protected]511f6f52010-12-17 03:58:297615
7616 EXPECT_EQ(302, response->headers->response_code());
7617 std::string url;
7618 EXPECT_TRUE(response->headers->IsRedirect(&url));
7619 EXPECT_EQ("http://login.example.com/", url);
[email protected]029c83b62013-01-24 05:28:207620
7621 // In the case of redirects from proxies, HttpNetworkTransaction returns
7622 // timing for the proxy connection instead of the connection to the host,
7623 // and no send / receive times.
7624 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
7625 LoadTimingInfo load_timing_info;
7626 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7627
7628 EXPECT_FALSE(load_timing_info.socket_reused);
ttuttle859dc7a2015-04-23 19:42:297629 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
[email protected]029c83b62013-01-24 05:28:207630
7631 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
7632 EXPECT_LE(load_timing_info.proxy_resolve_start,
7633 load_timing_info.proxy_resolve_end);
7634 EXPECT_LE(load_timing_info.proxy_resolve_end,
7635 load_timing_info.connect_timing.connect_start);
7636 ExpectConnectTimingHasTimes(
7637 load_timing_info.connect_timing,
7638 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
7639
7640 EXPECT_TRUE(load_timing_info.send_start.is_null());
7641 EXPECT_TRUE(load_timing_info.send_end.is_null());
7642 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
[email protected]511f6f52010-12-17 03:58:297643}
7644
7645// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
bncd16676a2016-07-20 16:23:017646TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037647 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297648
7649 HttpRequestInfo request;
7650 request.method = "GET";
bncce36dca22015-04-21 22:11:237651 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297652 request.load_flags = 0;
7653
bncdf80d44fd2016-07-15 20:27:417654 SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237655 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:417656 SpdySerializedFrame goaway(
[email protected]c10b20852013-05-15 21:29:207657 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297658 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:417659 CreateMockWrite(conn, 0, SYNCHRONOUS),
7660 CreateMockWrite(goaway, 2, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:297661 };
7662
7663 static const char* const kExtraHeaders[] = {
7664 "location",
7665 "http://login.example.com/",
7666 };
bnc42331402016-07-25 13:36:157667 SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
bncdf80d44fd2016-07-15 20:27:417668 "302 Redirect", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
[email protected]511f6f52010-12-17 03:58:297669 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:417670 CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3), // EOF
[email protected]511f6f52010-12-17 03:58:297671 };
7672
rch8e6c6c42015-05-01 14:05:137673 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7674 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067675 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:367676 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:297677
[email protected]bb88e1d32013-05-03 23:11:077678 session_deps_.socket_factory->AddSocketDataProvider(&data);
7679 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297680
[email protected]49639fa2011-12-20 23:22:417681 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297682
danakj1fd259a02016-04-16 03:17:097683 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7684 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417685 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297686
[email protected]49639fa2011-12-20 23:22:417687 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017688 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:297689
7690 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017691 EXPECT_THAT(rv, IsOk());
[email protected]511f6f52010-12-17 03:58:297692 const HttpResponseInfo* response = trans->GetResponseInfo();
7693
wezca1070932016-05-26 20:30:527694 ASSERT_TRUE(response);
[email protected]511f6f52010-12-17 03:58:297695
7696 EXPECT_EQ(302, response->headers->response_code());
7697 std::string url;
7698 EXPECT_TRUE(response->headers->IsRedirect(&url));
7699 EXPECT_EQ("http://login.example.com/", url);
7700}
7701
[email protected]4eddbc732012-08-09 05:40:177702// Test that an HTTPS proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:017703TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:037704 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297705
7706 HttpRequestInfo request;
7707 request.method = "GET";
bncce36dca22015-04-21 22:11:237708 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297709 request.load_flags = 0;
7710
7711 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:177712 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
7713 "Host: www.example.org:443\r\n"
7714 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]511f6f52010-12-17 03:58:297715 };
7716
7717 MockRead data_reads[] = {
7718 MockRead("HTTP/1.1 404 Not Found\r\n"),
7719 MockRead("Content-Length: 23\r\n\r\n"),
7720 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:067721 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:297722 };
7723
7724 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7725 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067726 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:297727
[email protected]bb88e1d32013-05-03 23:11:077728 session_deps_.socket_factory->AddSocketDataProvider(&data);
7729 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297730
[email protected]49639fa2011-12-20 23:22:417731 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297732
danakj1fd259a02016-04-16 03:17:097733 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7734 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417735 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297736
[email protected]49639fa2011-12-20 23:22:417737 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017738 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:297739
7740 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017741 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:297742
ttuttle960fcbf2016-04-19 13:26:327743 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297744}
7745
[email protected]4eddbc732012-08-09 05:40:177746// Test that a SPDY proxy's response to a CONNECT request is filtered.
bncd16676a2016-07-20 16:23:017747TEST_F(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
rdsmith82957ad2015-09-16 19:42:037748 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]511f6f52010-12-17 03:58:297749
7750 HttpRequestInfo request;
7751 request.method = "GET";
bncce36dca22015-04-21 22:11:237752 request.url = GURL("https://www.example.org/");
[email protected]511f6f52010-12-17 03:58:297753 request.load_flags = 0;
7754
bncdf80d44fd2016-07-15 20:27:417755 SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237756 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:417757 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:207758 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]511f6f52010-12-17 03:58:297759 MockWrite data_writes[] = {
bncdf80d44fd2016-07-15 20:27:417760 CreateMockWrite(conn, 0), CreateMockWrite(rst, 3),
[email protected]511f6f52010-12-17 03:58:297761 };
7762
7763 static const char* const kExtraHeaders[] = {
7764 "location",
7765 "http://login.example.com/",
7766 };
bnc42331402016-07-25 13:36:157767 SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
bncdf80d44fd2016-07-15 20:27:417768 "404 Not Found", kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
7769 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(
bncb03b1092016-04-06 11:19:557770 1, "The host does not exist", 23, true));
[email protected]511f6f52010-12-17 03:58:297771 MockRead data_reads[] = {
bncdf80d44fd2016-07-15 20:27:417772 CreateMockRead(resp, 1), CreateMockRead(body, 2),
rch8e6c6c42015-05-01 14:05:137773 MockRead(ASYNC, 0, 4), // EOF
[email protected]511f6f52010-12-17 03:58:297774 };
7775
rch8e6c6c42015-05-01 14:05:137776 SequencedSocketData data(data_reads, arraysize(data_reads), data_writes,
7777 arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:067778 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
bnc3cf2a592016-08-11 14:48:367779 proxy_ssl.next_proto = kProtoHTTP2;
[email protected]511f6f52010-12-17 03:58:297780
[email protected]bb88e1d32013-05-03 23:11:077781 session_deps_.socket_factory->AddSocketDataProvider(&data);
7782 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
[email protected]511f6f52010-12-17 03:58:297783
[email protected]49639fa2011-12-20 23:22:417784 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:297785
danakj1fd259a02016-04-16 03:17:097786 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7787 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:417788 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]511f6f52010-12-17 03:58:297789
[email protected]49639fa2011-12-20 23:22:417790 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:017791 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]511f6f52010-12-17 03:58:297792
7793 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:017794 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]511f6f52010-12-17 03:58:297795
ttuttle960fcbf2016-04-19 13:26:327796 // TODO(juliatuttle): Anything else to check here?
[email protected]511f6f52010-12-17 03:58:297797}
7798
[email protected]0c5fb722012-02-28 11:50:357799// Test the request-challenge-retry sequence for basic auth, through
7800// a SPDY proxy over a single SPDY session.
bncd16676a2016-07-20 16:23:017801TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
[email protected]0c5fb722012-02-28 11:50:357802 HttpRequestInfo request;
7803 request.method = "GET";
bncce36dca22015-04-21 22:11:237804 request.url = GURL("https://www.example.org/");
[email protected]0c5fb722012-02-28 11:50:357805 // when the no authentication data flag is set.
ttuttle859dc7a2015-04-23 19:42:297806 request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]0c5fb722012-02-28 11:50:357807
7808 // Configure against https proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:037809 session_deps_.proxy_service =
7810 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70");
vishal.b62985ca92015-04-17 08:45:517811 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077812 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:097813 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0c5fb722012-02-28 11:50:357814
7815 // Since we have proxy, should try to establish tunnel.
bncdf80d44fd2016-07-15 20:27:417816 SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:237817 NULL, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
bncdf80d44fd2016-07-15 20:27:417818 SpdySerializedFrame rst(
[email protected]c10b20852013-05-15 21:29:207819 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
rdsmithebb50aa2015-11-12 03:44:387820 spdy_util_.UpdateWithStreamDestruction(1);
[email protected]0c5fb722012-02-28 11:50:357821
7822 // After calling trans->RestartWithAuth(), this is the request we should
7823 // be issuing -- the final header line contains the credentials.
7824 const char* const kAuthCredentials[] = {
7825 "proxy-authorization", "Basic Zm9vOmJhcg==",
7826 };
bncdf80d44fd2016-07-15 20:27:417827 SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
lgarrona91df87f2014-12-05 00:51:347828 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST,
bncce36dca22015-04-21 22:11:237829 HostPortPair("www.example.org", 443)));
7830 // fetch https://www.example.org/ via HTTP
7831 const char get[] =
7832 "GET / HTTP/1.1\r\n"
7833 "Host: www.example.org\r\n"
7834 "Connection: keep-alive\r\n\r\n";
bncdf80d44fd2016-07-15 20:27:417835 SpdySerializedFrame wrapped_get(
7836 spdy_util_.ConstructSpdyDataFrame(3, get, strlen(get), false));
[email protected]0c5fb722012-02-28 11:50:357837
7838 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417839 CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 2, ASYNC),
7840 CreateMockWrite(connect2, 3), CreateMockWrite(wrapped_get, 5),
[email protected]0c5fb722012-02-28 11:50:357841 };
7842
7843 // The proxy responds to the connect with a 407, using a persistent
7844 // connection.
thestig9d3bb0c2015-01-24 00:49:517845 const char kAuthStatus[] = "407";
[email protected]0c5fb722012-02-28 11:50:357846 const char* const kAuthChallenge[] = {
[email protected]0c5fb722012-02-28 11:50:357847 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
7848 };
bnc42331402016-07-25 13:36:157849 SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
bncdf80d44fd2016-07-15 20:27:417850 kAuthStatus, kAuthChallenge, arraysize(kAuthChallenge) / 2, 1));
[email protected]0c5fb722012-02-28 11:50:357851
bnc42331402016-07-25 13:36:157852 SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
[email protected]0c5fb722012-02-28 11:50:357853 const char resp[] = "HTTP/1.1 200 OK\r\n"
7854 "Content-Length: 5\r\n\r\n";
7855
bncdf80d44fd2016-07-15 20:27:417856 SpdySerializedFrame wrapped_get_resp(
7857 spdy_util_.ConstructSpdyDataFrame(3, resp, strlen(resp), false));
7858 SpdySerializedFrame wrapped_body(
7859 spdy_util_.ConstructSpdyDataFrame(3, "hello", 5, false));
[email protected]0c5fb722012-02-28 11:50:357860 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417861 CreateMockRead(conn_auth_resp, 1, ASYNC),
7862 CreateMockRead(conn_resp, 4, ASYNC),
7863 CreateMockRead(wrapped_get_resp, 6, ASYNC),
7864 CreateMockRead(wrapped_body, 7, ASYNC),
rch8e6c6c42015-05-01 14:05:137865 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
[email protected]0c5fb722012-02-28 11:50:357866 };
7867
rch8e6c6c42015-05-01 14:05:137868 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7869 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077870 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]0c5fb722012-02-28 11:50:357871 // Negotiate SPDY to the proxy
7872 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367873 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:077874 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]0c5fb722012-02-28 11:50:357875 // Vanilla SSL to the server
7876 SSLSocketDataProvider server(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:077877 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
[email protected]0c5fb722012-02-28 11:50:357878
7879 TestCompletionCallback callback1;
7880
danakj1fd259a02016-04-16 03:17:097881 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507882 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0c5fb722012-02-28 11:50:357883
7884 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017885 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:357886
7887 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:017888 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:467889 TestNetLogEntry::List entries;
[email protected]0c5fb722012-02-28 11:50:357890 log.GetEntries(&entries);
7891 size_t pos = ExpectLogContainsSomewhere(
7892 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7893 NetLog::PHASE_NONE);
7894 ExpectLogContainsSomewhere(
7895 entries, pos,
7896 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7897 NetLog::PHASE_NONE);
7898
7899 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527900 ASSERT_TRUE(response);
7901 ASSERT_TRUE(response->headers);
[email protected]0c5fb722012-02-28 11:50:357902 EXPECT_EQ(407, response->headers->response_code());
7903 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
wezca1070932016-05-26 20:30:527904 EXPECT_TRUE(response->auth_challenge);
asanka098c0092016-06-16 20:18:437905 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge.get()));
[email protected]0c5fb722012-02-28 11:50:357906
7907 TestCompletionCallback callback2;
7908
7909 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
7910 callback2.callback());
robpercival214763f2016-07-01 23:27:017911 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0c5fb722012-02-28 11:50:357912
7913 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:017914 EXPECT_THAT(rv, IsOk());
[email protected]0c5fb722012-02-28 11:50:357915
7916 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:527917 ASSERT_TRUE(response);
[email protected]0c5fb722012-02-28 11:50:357918
7919 EXPECT_TRUE(response->headers->IsKeepAlive());
7920 EXPECT_EQ(200, response->headers->response_code());
7921 EXPECT_EQ(5, response->headers->GetContentLength());
7922 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7923
7924 // The password prompt info should not be set.
wezca1070932016-05-26 20:30:527925 EXPECT_FALSE(response->auth_challenge);
[email protected]0c5fb722012-02-28 11:50:357926
[email protected]029c83b62013-01-24 05:28:207927 LoadTimingInfo load_timing_info;
7928 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7929 TestLoadTimingNotReusedWithPac(load_timing_info,
7930 CONNECT_TIMING_HAS_SSL_TIMES);
7931
[email protected]0c5fb722012-02-28 11:50:357932 trans.reset();
7933 session->CloseAllConnections();
7934}
7935
[email protected]7c6f7ba2012-04-03 04:09:297936// Test that an explicitly trusted SPDY proxy can push a resource from an
7937// origin that is different from that of its associated resource.
bncd16676a2016-07-20 16:23:017938TEST_F(HttpNetworkTransactionTest, CrossOriginSPDYProxyPush) {
tbansal28e68f82016-02-04 02:56:157939 // Configure the proxy delegate to allow cross-origin SPDY pushes.
danakj1fd259a02016-04-16 03:17:097940 std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
tbansal28e68f82016-02-04 02:56:157941 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
7942 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]7c6f7ba2012-04-03 04:09:297943 HttpRequestInfo request;
7944 HttpRequestInfo push_request;
7945
[email protected]7c6f7ba2012-04-03 04:09:297946 request.method = "GET";
bncce36dca22015-04-21 22:11:237947 request.url = GURL("http://www.example.org/");
[email protected]7c6f7ba2012-04-03 04:09:297948 push_request.method = "GET";
7949 push_request.url = GURL("http://www.another-origin.com/foo.dat");
7950
tbansal28e68f82016-02-04 02:56:157951 // Configure against https proxy server "myproxy:443".
rdsmith82957ad2015-09-16 19:42:037952 session_deps_.proxy_service =
tbansal28e68f82016-02-04 02:56:157953 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:443");
vishal.b62985ca92015-04-17 08:45:517954 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:077955 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:507956
tbansal28e68f82016-02-04 02:56:157957 session_deps_.proxy_delegate.reset(proxy_delegate.release());
[email protected]61b4efc2012-04-27 18:12:507958
danakj1fd259a02016-04-16 03:17:097959 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7c6f7ba2012-04-03 04:09:297960
bncdf80d44fd2016-07-15 20:27:417961 SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:457962 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]7c6f7ba2012-04-03 04:09:297963
7964 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:417965 CreateMockWrite(stream1_syn, 0, ASYNC),
[email protected]7c6f7ba2012-04-03 04:09:297966 };
7967
bncdf80d44fd2016-07-15 20:27:417968 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:157969 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]7c6f7ba2012-04-03 04:09:297970
bncdf80d44fd2016-07-15 20:27:417971 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]7c6f7ba2012-04-03 04:09:297972
bncdf80d44fd2016-07-15 20:27:417973 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bncb03b1092016-04-06 11:19:557974 NULL, 0, 2, 1, "http://www.another-origin.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:437975 const char kPushedData[] = "pushed";
bncdf80d44fd2016-07-15 20:27:417976 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(
7977 2, kPushedData, strlen(kPushedData), true));
[email protected]7c6f7ba2012-04-03 04:09:297978
7979 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:417980 CreateMockRead(stream1_reply, 1, ASYNC),
7981 CreateMockRead(stream2_syn, 2, ASYNC),
7982 CreateMockRead(stream1_body, 3, ASYNC),
7983 CreateMockRead(stream2_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:597984 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]7c6f7ba2012-04-03 04:09:297985 };
7986
rch8e6c6c42015-05-01 14:05:137987 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
7988 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:077989 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]7c6f7ba2012-04-03 04:09:297990 // Negotiate SPDY to the proxy
7991 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:367992 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:077993 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]7c6f7ba2012-04-03 04:09:297994
danakj1fd259a02016-04-16 03:17:097995 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:507996 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]7c6f7ba2012-04-03 04:09:297997 TestCompletionCallback callback;
7998 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:017999 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:298000
8001 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018002 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:298003 const HttpResponseInfo* response = trans->GetResponseInfo();
8004
danakj1fd259a02016-04-16 03:17:098005 std::unique_ptr<HttpTransaction> push_trans(
[email protected]90499482013-06-01 00:39:508006 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8007 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:018008 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7c6f7ba2012-04-03 04:09:298009
8010 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018011 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:298012 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
8013
wezca1070932016-05-26 20:30:528014 ASSERT_TRUE(response);
[email protected]7c6f7ba2012-04-03 04:09:298015 EXPECT_TRUE(response->headers->IsKeepAlive());
8016
8017 EXPECT_EQ(200, response->headers->response_code());
8018 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8019
8020 std::string response_data;
8021 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018022 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:298023 EXPECT_EQ("hello!", response_data);
8024
[email protected]029c83b62013-01-24 05:28:208025 LoadTimingInfo load_timing_info;
8026 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8027 TestLoadTimingNotReusedWithPac(load_timing_info,
8028 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8029
[email protected]7c6f7ba2012-04-03 04:09:298030 // Verify the pushed stream.
wezca1070932016-05-26 20:30:528031 EXPECT_TRUE(push_response->headers);
[email protected]7c6f7ba2012-04-03 04:09:298032 EXPECT_EQ(200, push_response->headers->response_code());
8033
8034 rv = ReadTransaction(push_trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018035 EXPECT_THAT(rv, IsOk());
[email protected]7c6f7ba2012-04-03 04:09:298036 EXPECT_EQ("pushed", response_data);
8037
[email protected]029c83b62013-01-24 05:28:208038 LoadTimingInfo push_load_timing_info;
8039 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
8040 TestLoadTimingReusedWithPac(push_load_timing_info);
8041 // The transactions should share a socket ID, despite being for different
8042 // origins.
8043 EXPECT_EQ(load_timing_info.socket_log_id,
8044 push_load_timing_info.socket_log_id);
8045
[email protected]7c6f7ba2012-04-03 04:09:298046 trans.reset();
8047 push_trans.reset();
8048 session->CloseAllConnections();
8049}
8050
[email protected]8c843192012-04-05 07:15:008051// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
bncd16676a2016-07-20 16:23:018052TEST_F(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:158053 // Configure the proxy delegate to allow cross-origin SPDY pushes.
danakj1fd259a02016-04-16 03:17:098054 std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
tbansal28e68f82016-02-04 02:56:158055 proxy_delegate->set_trusted_spdy_proxy(net::ProxyServer::FromURI(
8056 "https://myproxy:443", net::ProxyServer::SCHEME_HTTP));
[email protected]8c843192012-04-05 07:15:008057 HttpRequestInfo request;
8058
8059 request.method = "GET";
bncce36dca22015-04-21 22:11:238060 request.url = GURL("http://www.example.org/");
[email protected]8c843192012-04-05 07:15:008061
tbansal28e68f82016-02-04 02:56:158062 session_deps_.proxy_service =
8063 ProxyService::CreateFixed("https://myproxy:443");
vishal.b62985ca92015-04-17 08:45:518064 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:078065 session_deps_.net_log = log.bound().net_log();
[email protected]61b4efc2012-04-27 18:12:508066
8067 // Enable cross-origin push.
tbansal28e68f82016-02-04 02:56:158068 session_deps_.proxy_delegate.reset(proxy_delegate.release());
[email protected]61b4efc2012-04-27 18:12:508069
danakj1fd259a02016-04-16 03:17:098070 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8c843192012-04-05 07:15:008071
bncdf80d44fd2016-07-15 20:27:418072 SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:458073 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
[email protected]8c843192012-04-05 07:15:008074
bncdf80d44fd2016-07-15 20:27:418075 SpdySerializedFrame push_rst(
[email protected]c10b20852013-05-15 21:29:208076 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]8c843192012-04-05 07:15:008077
8078 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:418079 CreateMockWrite(stream1_syn, 0, ASYNC), CreateMockWrite(push_rst, 3),
[email protected]8c843192012-04-05 07:15:008080 };
8081
bncdf80d44fd2016-07-15 20:27:418082 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:158083 spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
[email protected]8c843192012-04-05 07:15:008084
bncdf80d44fd2016-07-15 20:27:418085 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]8c843192012-04-05 07:15:008086
bncdf80d44fd2016-07-15 20:27:418087 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bncb03b1092016-04-06 11:19:558088 NULL, 0, 2, 1, "https://www.another-origin.com/foo.dat"));
[email protected]8c843192012-04-05 07:15:008089
8090 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:418091 CreateMockRead(stream1_reply, 1, ASYNC),
8092 CreateMockRead(stream2_syn, 2, ASYNC),
8093 CreateMockRead(stream1_body, 4, ASYNC),
mmenkee24011922015-12-17 22:12:598094 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
[email protected]8c843192012-04-05 07:15:008095 };
8096
rch8e6c6c42015-05-01 14:05:138097 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
8098 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:078099 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]8c843192012-04-05 07:15:008100 // Negotiate SPDY to the proxy
8101 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:368102 proxy.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:078103 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
[email protected]8c843192012-04-05 07:15:008104
danakj1fd259a02016-04-16 03:17:098105 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:508106 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c843192012-04-05 07:15:008107 TestCompletionCallback callback;
8108 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:018109 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c843192012-04-05 07:15:008110
8111 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018112 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:008113 const HttpResponseInfo* response = trans->GetResponseInfo();
8114
wezca1070932016-05-26 20:30:528115 ASSERT_TRUE(response);
[email protected]8c843192012-04-05 07:15:008116 EXPECT_TRUE(response->headers->IsKeepAlive());
8117
8118 EXPECT_EQ(200, response->headers->response_code());
8119 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8120
8121 std::string response_data;
8122 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018123 EXPECT_THAT(rv, IsOk());
[email protected]8c843192012-04-05 07:15:008124 EXPECT_EQ("hello!", response_data);
8125
8126 trans.reset();
8127 session->CloseAllConnections();
8128}
8129
tbansal8ef1d3e2016-02-03 04:05:428130// Test that an explicitly trusted SPDY proxy can push same-origin HTTPS
8131// resources.
bncd16676a2016-07-20 16:23:018132TEST_F(HttpNetworkTransactionTest, SameOriginProxyPushCorrectness) {
tbansal28e68f82016-02-04 02:56:158133 // Configure the proxy delegate to allow cross-origin SPDY pushes.
danakj1fd259a02016-04-16 03:17:098134 std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
tbansal28e68f82016-02-04 02:56:158135 proxy_delegate->set_trusted_spdy_proxy(
8136 net::ProxyServer::FromURI("myproxy:70", net::ProxyServer::SCHEME_HTTP));
8137
tbansal8ef1d3e2016-02-03 04:05:428138 HttpRequestInfo request;
8139
8140 request.method = "GET";
8141 request.url = GURL("http://www.example.org/");
8142
8143 // Configure against https proxy server "myproxy:70".
8144 session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70");
8145 BoundTestNetLog log;
8146 session_deps_.net_log = log.bound().net_log();
8147
8148 // Enable cross-origin push.
tbansal28e68f82016-02-04 02:56:158149 session_deps_.proxy_delegate.reset(proxy_delegate.release());
tbansal8ef1d3e2016-02-03 04:05:428150
danakj1fd259a02016-04-16 03:17:098151 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
tbansal8ef1d3e2016-02-03 04:05:428152
bncdf80d44fd2016-07-15 20:27:418153 SpdySerializedFrame stream1_syn(
bncb26024382016-06-29 02:39:458154 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
tbansal8ef1d3e2016-02-03 04:05:428155
8156 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:418157 CreateMockWrite(stream1_syn, 0, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:428158 };
8159
bncdf80d44fd2016-07-15 20:27:418160 SpdySerializedFrame stream1_reply(
bnc42331402016-07-25 13:36:158161 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:428162
bncdf80d44fd2016-07-15 20:27:418163 SpdySerializedFrame stream2_syn(spdy_util_.ConstructSpdyPush(
bnc38dcd392016-02-09 23:19:498164 nullptr, 0, 2, 1, "https://myproxy:70/foo.dat"));
8165
bncdf80d44fd2016-07-15 20:27:418166 SpdySerializedFrame stream1_body(spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:428167
bncdf80d44fd2016-07-15 20:27:418168 SpdySerializedFrame stream2_reply(
bnc42331402016-07-25 13:36:158169 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
tbansal8ef1d3e2016-02-03 04:05:428170
bncdf80d44fd2016-07-15 20:27:418171 SpdySerializedFrame stream2_body(spdy_util_.ConstructSpdyDataFrame(1, true));
tbansal8ef1d3e2016-02-03 04:05:428172
8173 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:418174 CreateMockRead(stream1_reply, 1, ASYNC),
8175 CreateMockRead(stream2_syn, 2, ASYNC),
8176 CreateMockRead(stream1_body, 3, ASYNC),
8177 CreateMockRead(stream2_body, 4, ASYNC),
tbansal8ef1d3e2016-02-03 04:05:428178 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a hang
8179 };
8180
8181 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
8182 arraysize(spdy_writes));
8183 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8184 // Negotiate SPDY to the proxy
8185 SSLSocketDataProvider proxy(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:368186 proxy.next_proto = kProtoHTTP2;
tbansal8ef1d3e2016-02-03 04:05:428187 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
8188
danakj1fd259a02016-04-16 03:17:098189 std::unique_ptr<HttpTransaction> trans(
tbansal8ef1d3e2016-02-03 04:05:428190 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8191 TestCompletionCallback callback;
8192 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:018193 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
tbansal8ef1d3e2016-02-03 04:05:428194
8195 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018196 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:428197 const HttpResponseInfo* response = trans->GetResponseInfo();
8198
wezca1070932016-05-26 20:30:528199 ASSERT_TRUE(response);
tbansal8ef1d3e2016-02-03 04:05:428200 EXPECT_TRUE(response->headers->IsKeepAlive());
8201
8202 EXPECT_EQ(200, response->headers->response_code());
8203 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8204
8205 std::string response_data;
8206 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:018207 EXPECT_THAT(rv, IsOk());
tbansal8ef1d3e2016-02-03 04:05:428208 EXPECT_EQ("hello!", response_data);
8209
8210 trans.reset();
8211 session->CloseAllConnections();
8212}
8213
[email protected]2df19bb2010-08-25 20:13:468214// Test HTTPS connections to a site with a bad certificate, going through an
8215// HTTPS proxy
bncd16676a2016-07-20 16:23:018216TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
rdsmith82957ad2015-09-16 19:42:038217 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
[email protected]2df19bb2010-08-25 20:13:468218
8219 HttpRequestInfo request;
8220 request.method = "GET";
bncce36dca22015-04-21 22:11:238221 request.url = GURL("https://www.example.org/");
[email protected]2df19bb2010-08-25 20:13:468222 request.load_flags = 0;
8223
8224 // Attempt to fetch the URL from a server with a bad cert
8225 MockWrite bad_cert_writes[] = {
rsleevidb16bb02015-11-12 23:47:178226 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8227 "Host: www.example.org:443\r\n"
8228 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:468229 };
8230
8231 MockRead bad_cert_reads[] = {
8232 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068233 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:468234 };
8235
8236 // Attempt to fetch the URL with a good cert
8237 MockWrite good_data_writes[] = {
rsleevidb16bb02015-11-12 23:47:178238 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8239 "Host: www.example.org:443\r\n"
8240 "Proxy-Connection: keep-alive\r\n\r\n"),
8241 MockWrite("GET / HTTP/1.1\r\n"
8242 "Host: www.example.org\r\n"
8243 "Connection: keep-alive\r\n\r\n"),
[email protected]2df19bb2010-08-25 20:13:468244 };
8245
8246 MockRead good_cert_reads[] = {
8247 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
8248 MockRead("HTTP/1.0 200 OK\r\n"),
8249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8250 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068251 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:468252 };
8253
8254 StaticSocketDataProvider ssl_bad_certificate(
8255 bad_cert_reads, arraysize(bad_cert_reads),
8256 bad_cert_writes, arraysize(bad_cert_writes));
8257 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
8258 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:068259 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
8260 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:468261
8262 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
[email protected]bb88e1d32013-05-03 23:11:078263 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8264 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
8265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
[email protected]2df19bb2010-08-25 20:13:468266
8267 // SSL to the proxy, then CONNECT request, then valid SSL certificate
[email protected]bb88e1d32013-05-03 23:11:078268 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8269 session_deps_.socket_factory->AddSocketDataProvider(&data);
8270 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2df19bb2010-08-25 20:13:468271
[email protected]49639fa2011-12-20 23:22:418272 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:468273
danakj1fd259a02016-04-16 03:17:098274 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8275 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418276 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2df19bb2010-08-25 20:13:468277
[email protected]49639fa2011-12-20 23:22:418278 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018279 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:468280
8281 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018282 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
[email protected]2df19bb2010-08-25 20:13:468283
[email protected]49639fa2011-12-20 23:22:418284 rv = trans->RestartIgnoringLastError(callback.callback());
robpercival214763f2016-07-01 23:27:018285 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2df19bb2010-08-25 20:13:468286
8287 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018288 EXPECT_THAT(rv, IsOk());
[email protected]2df19bb2010-08-25 20:13:468289
8290 const HttpResponseInfo* response = trans->GetResponseInfo();
8291
wezca1070932016-05-26 20:30:528292 ASSERT_TRUE(response);
[email protected]2df19bb2010-08-25 20:13:468293 EXPECT_EQ(100, response->headers->GetContentLength());
8294}
8295
bncd16676a2016-07-20 16:23:018296TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:428297 HttpRequestInfo request;
8298 request.method = "GET";
bncce36dca22015-04-21 22:11:238299 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438300 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
8301 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:428302
danakj1fd259a02016-04-16 03:17:098303 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8304 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418305 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278306
[email protected]1c773ea12009-04-28 19:58:428307 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238308 MockWrite(
8309 "GET / HTTP/1.1\r\n"
8310 "Host: www.example.org\r\n"
8311 "Connection: keep-alive\r\n"
8312 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428313 };
8314
8315 // Lastly, the server responds with the actual content.
8316 MockRead data_reads[] = {
8317 MockRead("HTTP/1.0 200 OK\r\n"),
8318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8319 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068320 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428321 };
8322
[email protected]31a2bfe2010-02-09 08:03:398323 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8324 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078325 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428326
[email protected]49639fa2011-12-20 23:22:418327 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428328
[email protected]49639fa2011-12-20 23:22:418329 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428331
8332 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018333 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428334}
8335
bncd16676a2016-07-20 16:23:018336TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:298337 HttpRequestInfo request;
8338 request.method = "GET";
bncce36dca22015-04-21 22:11:238339 request.url = GURL("https://www.example.org/");
[email protected]da81f132010-08-18 23:39:298340 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
8341 "Chromium Ultra Awesome X Edition");
8342
rdsmith82957ad2015-09-16 19:42:038343 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
danakj1fd259a02016-04-16 03:17:098344 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8345 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418346 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278347
[email protected]da81f132010-08-18 23:39:298348 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:178349 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
8350 "Host: www.example.org:443\r\n"
8351 "Proxy-Connection: keep-alive\r\n"
8352 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
[email protected]da81f132010-08-18 23:39:298353 };
8354 MockRead data_reads[] = {
8355 // Return an error, so the transaction stops here (this test isn't
8356 // interested in the rest).
8357 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
8358 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8359 MockRead("Proxy-Connection: close\r\n\r\n"),
8360 };
8361
8362 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8363 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078364 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]da81f132010-08-18 23:39:298365
[email protected]49639fa2011-12-20 23:22:418366 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:298367
[email protected]49639fa2011-12-20 23:22:418368 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018369 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]da81f132010-08-18 23:39:298370
8371 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018372 EXPECT_THAT(rv, IsOk());
[email protected]da81f132010-08-18 23:39:298373}
8374
bncd16676a2016-07-20 16:23:018375TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:428376 HttpRequestInfo request;
8377 request.method = "GET";
bncce36dca22015-04-21 22:11:238378 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428379 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:168380 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
8381 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:428382
danakj1fd259a02016-04-16 03:17:098383 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8384 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418385 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278386
[email protected]1c773ea12009-04-28 19:58:428387 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238388 MockWrite(
8389 "GET / HTTP/1.1\r\n"
8390 "Host: www.example.org\r\n"
8391 "Connection: keep-alive\r\n"
8392 "Referer: http://the.previous.site.com/\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428393 };
8394
8395 // Lastly, the server responds with the actual content.
8396 MockRead data_reads[] = {
8397 MockRead("HTTP/1.0 200 OK\r\n"),
8398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8399 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068400 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428401 };
8402
[email protected]31a2bfe2010-02-09 08:03:398403 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8404 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078405 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428406
[email protected]49639fa2011-12-20 23:22:418407 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428408
[email protected]49639fa2011-12-20 23:22:418409 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018410 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428411
8412 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018413 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428414}
8415
bncd16676a2016-07-20 16:23:018416TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428417 HttpRequestInfo request;
8418 request.method = "POST";
bncce36dca22015-04-21 22:11:238419 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428420
danakj1fd259a02016-04-16 03:17:098421 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8422 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418423 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278424
[email protected]1c773ea12009-04-28 19:58:428425 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238426 MockWrite(
8427 "POST / HTTP/1.1\r\n"
8428 "Host: www.example.org\r\n"
8429 "Connection: keep-alive\r\n"
8430 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428431 };
8432
8433 // Lastly, the server responds with the actual content.
8434 MockRead data_reads[] = {
8435 MockRead("HTTP/1.0 200 OK\r\n"),
8436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8437 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068438 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428439 };
8440
[email protected]31a2bfe2010-02-09 08:03:398441 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8442 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078443 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428444
[email protected]49639fa2011-12-20 23:22:418445 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428446
[email protected]49639fa2011-12-20 23:22:418447 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018448 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428449
8450 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018451 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428452}
8453
bncd16676a2016-07-20 16:23:018454TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428455 HttpRequestInfo request;
8456 request.method = "PUT";
bncce36dca22015-04-21 22:11:238457 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428458
danakj1fd259a02016-04-16 03:17:098459 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8460 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418461 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278462
[email protected]1c773ea12009-04-28 19:58:428463 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238464 MockWrite(
8465 "PUT / HTTP/1.1\r\n"
8466 "Host: www.example.org\r\n"
8467 "Connection: keep-alive\r\n"
8468 "Content-Length: 0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428469 };
8470
8471 // Lastly, the server responds with the actual content.
8472 MockRead data_reads[] = {
8473 MockRead("HTTP/1.0 200 OK\r\n"),
8474 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8475 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068476 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428477 };
8478
[email protected]31a2bfe2010-02-09 08:03:398479 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8480 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078481 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428482
[email protected]49639fa2011-12-20 23:22:418483 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428484
[email protected]49639fa2011-12-20 23:22:418485 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018486 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428487
8488 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018489 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428490}
8491
bncd16676a2016-07-20 16:23:018492TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:428493 HttpRequestInfo request;
8494 request.method = "HEAD";
bncce36dca22015-04-21 22:11:238495 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428496
danakj1fd259a02016-04-16 03:17:098497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8498 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418499 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278500
[email protected]1c773ea12009-04-28 19:58:428501 MockWrite data_writes[] = {
csharrisonf473dd192015-08-18 13:54:138502 MockWrite("HEAD / HTTP/1.1\r\n"
8503 "Host: www.example.org\r\n"
8504 "Connection: keep-alive\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428505 };
8506
8507 // Lastly, the server responds with the actual content.
8508 MockRead data_reads[] = {
8509 MockRead("HTTP/1.0 200 OK\r\n"),
8510 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8511 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068512 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428513 };
8514
[email protected]31a2bfe2010-02-09 08:03:398515 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8516 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078517 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428518
[email protected]49639fa2011-12-20 23:22:418519 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428520
[email protected]49639fa2011-12-20 23:22:418521 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018522 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428523
8524 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018525 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428526}
8527
bncd16676a2016-07-20 16:23:018528TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:428529 HttpRequestInfo request;
8530 request.method = "GET";
bncce36dca22015-04-21 22:11:238531 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428532 request.load_flags = LOAD_BYPASS_CACHE;
8533
danakj1fd259a02016-04-16 03:17:098534 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8535 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418536 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278537
[email protected]1c773ea12009-04-28 19:58:428538 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238539 MockWrite(
8540 "GET / HTTP/1.1\r\n"
8541 "Host: www.example.org\r\n"
8542 "Connection: keep-alive\r\n"
8543 "Pragma: no-cache\r\n"
8544 "Cache-Control: no-cache\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428545 };
8546
8547 // Lastly, the server responds with the actual content.
8548 MockRead data_reads[] = {
8549 MockRead("HTTP/1.0 200 OK\r\n"),
8550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8551 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068552 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428553 };
8554
[email protected]31a2bfe2010-02-09 08:03:398555 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8556 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078557 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428558
[email protected]49639fa2011-12-20 23:22:418559 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428560
[email protected]49639fa2011-12-20 23:22:418561 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018562 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428563
8564 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018565 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428566}
8567
bncd16676a2016-07-20 16:23:018568TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:428569 HttpRequestInfo request;
8570 request.method = "GET";
bncce36dca22015-04-21 22:11:238571 request.url = GURL("http://www.example.org/");
[email protected]1c773ea12009-04-28 19:58:428572 request.load_flags = LOAD_VALIDATE_CACHE;
8573
danakj1fd259a02016-04-16 03:17:098574 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8575 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418576 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278577
[email protected]1c773ea12009-04-28 19:58:428578 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238579 MockWrite(
8580 "GET / HTTP/1.1\r\n"
8581 "Host: www.example.org\r\n"
8582 "Connection: keep-alive\r\n"
8583 "Cache-Control: max-age=0\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428584 };
8585
8586 // Lastly, the server responds with the actual content.
8587 MockRead data_reads[] = {
8588 MockRead("HTTP/1.0 200 OK\r\n"),
8589 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8590 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068591 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428592 };
8593
[email protected]31a2bfe2010-02-09 08:03:398594 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8595 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078596 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428597
[email protected]49639fa2011-12-20 23:22:418598 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428599
[email protected]49639fa2011-12-20 23:22:418600 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018601 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428602
8603 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018604 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428605}
8606
bncd16676a2016-07-20 16:23:018607TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:428608 HttpRequestInfo request;
8609 request.method = "GET";
bncce36dca22015-04-21 22:11:238610 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438611 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:428612
danakj1fd259a02016-04-16 03:17:098613 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8614 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418615 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278616
[email protected]1c773ea12009-04-28 19:58:428617 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238618 MockWrite(
8619 "GET / HTTP/1.1\r\n"
8620 "Host: www.example.org\r\n"
8621 "Connection: keep-alive\r\n"
8622 "FooHeader: Bar\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:428623 };
8624
8625 // Lastly, the server responds with the actual content.
8626 MockRead data_reads[] = {
8627 MockRead("HTTP/1.0 200 OK\r\n"),
8628 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8629 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068630 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:428631 };
8632
[email protected]31a2bfe2010-02-09 08:03:398633 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8634 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078635 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:428636
[email protected]49639fa2011-12-20 23:22:418637 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:428638
[email protected]49639fa2011-12-20 23:22:418639 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018640 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]1c773ea12009-04-28 19:58:428641
8642 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018643 EXPECT_THAT(rv, IsOk());
[email protected]1c773ea12009-04-28 19:58:428644}
8645
bncd16676a2016-07-20 16:23:018646TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:478647 HttpRequestInfo request;
8648 request.method = "GET";
bncce36dca22015-04-21 22:11:238649 request.url = GURL("http://www.example.org/");
[email protected]8c76ae22010-04-20 22:15:438650 request.extra_headers.SetHeader("referer", "www.foo.com");
8651 request.extra_headers.SetHeader("hEllo", "Kitty");
8652 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:478653
danakj1fd259a02016-04-16 03:17:098654 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8655 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418656 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:278657
[email protected]270c6412010-03-29 22:02:478658 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238659 MockWrite(
8660 "GET / HTTP/1.1\r\n"
8661 "Host: www.example.org\r\n"
8662 "Connection: keep-alive\r\n"
8663 "referer: www.foo.com\r\n"
8664 "hEllo: Kitty\r\n"
8665 "FoO: bar\r\n\r\n"),
[email protected]270c6412010-03-29 22:02:478666 };
8667
8668 // Lastly, the server responds with the actual content.
8669 MockRead data_reads[] = {
8670 MockRead("HTTP/1.0 200 OK\r\n"),
8671 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8672 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068673 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:478674 };
8675
8676 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8677 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078678 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]270c6412010-03-29 22:02:478679
[email protected]49639fa2011-12-20 23:22:418680 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:478681
[email protected]49639fa2011-12-20 23:22:418682 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018683 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]270c6412010-03-29 22:02:478684
8685 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018686 EXPECT_THAT(rv, IsOk());
[email protected]270c6412010-03-29 22:02:478687}
8688
bncd16676a2016-07-20 16:23:018689TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278690 HttpRequestInfo request;
8691 request.method = "GET";
bncce36dca22015-04-21 22:11:238692 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278693 request.load_flags = 0;
8694
rdsmith82957ad2015-09-16 19:42:038695 session_deps_.proxy_service =
8696 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518697 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078698 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028699
danakj1fd259a02016-04-16 03:17:098700 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8701 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418702 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028703
[email protected]3cd17242009-06-23 02:59:028704 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8705 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8706
8707 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238708 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8709 MockWrite(
8710 "GET / HTTP/1.1\r\n"
8711 "Host: www.example.org\r\n"
8712 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028713
8714 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068715 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:028716 MockRead("HTTP/1.0 200 OK\r\n"),
8717 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8718 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068719 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028720 };
8721
[email protected]31a2bfe2010-02-09 08:03:398722 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8723 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078724 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028725
[email protected]49639fa2011-12-20 23:22:418726 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028727
[email protected]49639fa2011-12-20 23:22:418728 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018729 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:028730
8731 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018732 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:028733
8734 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528735 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:028736
[email protected]029c83b62013-01-24 05:28:208737 LoadTimingInfo load_timing_info;
8738 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8739 TestLoadTimingNotReusedWithPac(load_timing_info,
8740 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8741
[email protected]3cd17242009-06-23 02:59:028742 std::string response_text;
8743 rv = ReadTransaction(trans.get(), &response_text);
robpercival214763f2016-07-01 23:27:018744 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:028745 EXPECT_EQ("Payload", response_text);
8746}
8747
bncd16676a2016-07-20 16:23:018748TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278749 HttpRequestInfo request;
8750 request.method = "GET";
bncce36dca22015-04-21 22:11:238751 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278752 request.load_flags = 0;
8753
rdsmith82957ad2015-09-16 19:42:038754 session_deps_.proxy_service =
8755 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518756 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078757 session_deps_.net_log = &net_log;
[email protected]3cd17242009-06-23 02:59:028758
danakj1fd259a02016-04-16 03:17:098759 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8760 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418761 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3cd17242009-06-23 02:59:028762
[email protected]3cd17242009-06-23 02:59:028763 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
8764 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8765
8766 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238767 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
8768 arraysize(write_buffer)),
8769 MockWrite(
8770 "GET / HTTP/1.1\r\n"
8771 "Host: www.example.org\r\n"
8772 "Connection: keep-alive\r\n\r\n")};
[email protected]3cd17242009-06-23 02:59:028773
8774 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018775 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
8776 arraysize(read_buffer)),
[email protected]e0c27be2009-07-15 13:09:358777 MockRead("HTTP/1.0 200 OK\r\n"),
8778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8779 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068780 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358781 };
8782
[email protected]31a2bfe2010-02-09 08:03:398783 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8784 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078785 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358786
[email protected]8ddf8322012-02-23 18:08:068787 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:358789
[email protected]49639fa2011-12-20 23:22:418790 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358791
[email protected]49639fa2011-12-20 23:22:418792 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018793 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:358794
8795 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018796 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:358797
[email protected]029c83b62013-01-24 05:28:208798 LoadTimingInfo load_timing_info;
8799 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8800 TestLoadTimingNotReusedWithPac(load_timing_info,
8801 CONNECT_TIMING_HAS_SSL_TIMES);
8802
[email protected]e0c27be2009-07-15 13:09:358803 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528804 ASSERT_TRUE(response);
[email protected]e0c27be2009-07-15 13:09:358805
8806 std::string response_text;
8807 rv = ReadTransaction(trans.get(), &response_text);
robpercival214763f2016-07-01 23:27:018808 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:358809 EXPECT_EQ("Payload", response_text);
8810}
8811
bncd16676a2016-07-20 16:23:018812TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
[email protected]029c83b62013-01-24 05:28:208813 HttpRequestInfo request;
8814 request.method = "GET";
bncce36dca22015-04-21 22:11:238815 request.url = GURL("http://www.example.org/");
[email protected]029c83b62013-01-24 05:28:208816 request.load_flags = 0;
8817
rdsmith82957ad2015-09-16 19:42:038818 session_deps_.proxy_service =
8819 ProxyService::CreateFixed("socks4://myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518820 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078821 session_deps_.net_log = &net_log;
[email protected]029c83b62013-01-24 05:28:208822
danakj1fd259a02016-04-16 03:17:098823 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8824 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418825 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]029c83b62013-01-24 05:28:208826
8827 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
8828 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
8829
8830 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238831 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
8832 MockWrite(
8833 "GET / HTTP/1.1\r\n"
8834 "Host: www.example.org\r\n"
8835 "Connection: keep-alive\r\n\r\n")};
[email protected]029c83b62013-01-24 05:28:208836
8837 MockRead data_reads[] = {
8838 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
8839 MockRead("HTTP/1.0 200 OK\r\n"),
8840 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8841 MockRead("Payload"),
8842 MockRead(SYNCHRONOUS, OK)
8843 };
8844
8845 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8846 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078847 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]029c83b62013-01-24 05:28:208848
8849 TestCompletionCallback callback;
8850
8851 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018852 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]029c83b62013-01-24 05:28:208853
8854 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018855 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:208856
8857 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528858 ASSERT_TRUE(response);
[email protected]029c83b62013-01-24 05:28:208859
8860 LoadTimingInfo load_timing_info;
8861 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8862 TestLoadTimingNotReused(load_timing_info,
8863 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8864
8865 std::string response_text;
8866 rv = ReadTransaction(trans.get(), &response_text);
robpercival214763f2016-07-01 23:27:018867 EXPECT_THAT(rv, IsOk());
[email protected]029c83b62013-01-24 05:28:208868 EXPECT_EQ("Payload", response_text);
8869}
8870
bncd16676a2016-07-20 16:23:018871TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278872 HttpRequestInfo request;
8873 request.method = "GET";
bncce36dca22015-04-21 22:11:238874 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278875 request.load_flags = 0;
8876
rdsmith82957ad2015-09-16 19:42:038877 session_deps_.proxy_service =
8878 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518879 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078880 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358881
danakj1fd259a02016-04-16 03:17:098882 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8883 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418884 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358885
[email protected]e0c27be2009-07-15 13:09:358886 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8887 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378888 const char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238889 0x05, // Version
8890 0x01, // Command (CONNECT)
8891 0x00, // Reserved.
8892 0x03, // Address type (DOMAINNAME).
8893 0x0F, // Length of domain (15)
8894 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8895 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
[email protected]f209dba2009-12-18 00:24:378896 };
[email protected]e0c27be2009-07-15 13:09:358897 const char kSOCKS5OkResponse[] =
8898 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
8899
8900 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238901 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8902 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
8903 MockWrite(
8904 "GET / HTTP/1.1\r\n"
8905 "Host: www.example.org\r\n"
8906 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358907
8908 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018909 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8910 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:358911 MockRead("HTTP/1.0 200 OK\r\n"),
8912 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8913 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068914 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:358915 };
8916
[email protected]31a2bfe2010-02-09 08:03:398917 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8918 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078919 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:358920
[email protected]49639fa2011-12-20 23:22:418921 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:358922
[email protected]49639fa2011-12-20 23:22:418923 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:018924 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]e0c27be2009-07-15 13:09:358925
8926 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:018927 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:358928
8929 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:528930 ASSERT_TRUE(response);
[email protected]e0c27be2009-07-15 13:09:358931
[email protected]029c83b62013-01-24 05:28:208932 LoadTimingInfo load_timing_info;
8933 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8934 TestLoadTimingNotReusedWithPac(load_timing_info,
8935 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
8936
[email protected]e0c27be2009-07-15 13:09:358937 std::string response_text;
8938 rv = ReadTransaction(trans.get(), &response_text);
robpercival214763f2016-07-01 23:27:018939 EXPECT_THAT(rv, IsOk());
[email protected]e0c27be2009-07-15 13:09:358940 EXPECT_EQ("Payload", response_text);
8941}
8942
bncd16676a2016-07-20 16:23:018943TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:278944 HttpRequestInfo request;
8945 request.method = "GET";
bncce36dca22015-04-21 22:11:238946 request.url = GURL("https://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:278947 request.load_flags = 0;
8948
rdsmith82957ad2015-09-16 19:42:038949 session_deps_.proxy_service =
8950 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080");
vishal.b62985ca92015-04-17 08:45:518951 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:078952 session_deps_.net_log = &net_log;
[email protected]e0c27be2009-07-15 13:09:358953
danakj1fd259a02016-04-16 03:17:098954 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8955 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:418956 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]e0c27be2009-07-15 13:09:358957
[email protected]e0c27be2009-07-15 13:09:358958 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
8959 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:378960 const unsigned char kSOCKS5OkRequest[] = {
bncce36dca22015-04-21 22:11:238961 0x05, // Version
8962 0x01, // Command (CONNECT)
8963 0x00, // Reserved.
8964 0x03, // Address type (DOMAINNAME).
8965 0x0F, // Length of domain (15)
8966 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
8967 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
[email protected]f209dba2009-12-18 00:24:378968 };
8969
[email protected]e0c27be2009-07-15 13:09:358970 const char kSOCKS5OkResponse[] =
8971 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
8972
8973 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:238974 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
8975 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
8976 arraysize(kSOCKS5OkRequest)),
8977 MockWrite(
8978 "GET / HTTP/1.1\r\n"
8979 "Host: www.example.org\r\n"
8980 "Connection: keep-alive\r\n\r\n")};
[email protected]e0c27be2009-07-15 13:09:358981
8982 MockRead data_reads[] = {
[email protected]f871ee152012-07-27 19:02:018983 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
8984 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:028985 MockRead("HTTP/1.0 200 OK\r\n"),
8986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
8987 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:068988 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:028989 };
8990
[email protected]31a2bfe2010-02-09 08:03:398991 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8992 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:078993 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:028994
[email protected]8ddf8322012-02-23 18:08:068995 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:078996 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:028997
[email protected]49639fa2011-12-20 23:22:418998 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:028999
[email protected]49639fa2011-12-20 23:22:419000 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019001 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3cd17242009-06-23 02:59:029002
9003 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019004 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:029005
9006 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529007 ASSERT_TRUE(response);
[email protected]3cd17242009-06-23 02:59:029008
[email protected]029c83b62013-01-24 05:28:209009 LoadTimingInfo load_timing_info;
9010 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9011 TestLoadTimingNotReusedWithPac(load_timing_info,
9012 CONNECT_TIMING_HAS_SSL_TIMES);
9013
[email protected]3cd17242009-06-23 02:59:029014 std::string response_text;
9015 rv = ReadTransaction(trans.get(), &response_text);
robpercival214763f2016-07-01 23:27:019016 EXPECT_THAT(rv, IsOk());
[email protected]3cd17242009-06-23 02:59:029017 EXPECT_EQ("Payload", response_text);
9018}
9019
[email protected]448d4ca52012-03-04 04:12:239020namespace {
9021
[email protected]04e5be32009-06-26 20:00:319022// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:069023
9024struct GroupNameTest {
9025 std::string proxy_server;
9026 std::string url;
9027 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:189028 bool ssl;
[email protected]2d731a32010-04-29 01:04:069029};
9030
danakj1fd259a02016-04-16 03:17:099031std::unique_ptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]bb88e1d32013-05-03 23:11:079032 SpdySessionDependencies* session_deps_) {
danakj1fd259a02016-04-16 03:17:099033 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
[email protected]2d731a32010-04-29 01:04:069034
bnc525e175a2016-06-20 12:36:409035 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:539036 session->http_server_properties();
bnccacc0992015-03-20 20:22:229037 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:409038 AlternateProtocolFromNextProto(kProtoHTTP2), "", 444);
bnc7dc7e1b42015-07-28 14:43:129039 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:229040 http_server_properties->SetAlternativeService(
bncaa60ff402016-06-22 19:12:429041 url::SchemeHostPort("https", "host.with.alternate", 443),
zhongyi3d4a55e72016-04-22 20:36:469042 alternative_service, expiration);
[email protected]2d731a32010-04-29 01:04:069043
9044 return session;
9045}
9046
mmenkee65e7af2015-10-13 17:16:429047int GroupNameTransactionHelper(const std::string& url,
9048 HttpNetworkSession* session) {
[email protected]2d731a32010-04-29 01:04:069049 HttpRequestInfo request;
9050 request.method = "GET";
9051 request.url = GURL(url);
9052 request.load_flags = 0;
9053
danakj1fd259a02016-04-16 03:17:099054 std::unique_ptr<HttpTransaction> trans(
mmenkee65e7af2015-10-13 17:16:429055 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
[email protected]cb9bf6ca2011-01-28 13:15:279056
[email protected]49639fa2011-12-20 23:22:419057 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:069058
9059 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:419060 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:069061}
9062
[email protected]448d4ca52012-03-04 04:12:239063} // namespace
9064
bncd16676a2016-07-20 16:23:019065TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
[email protected]2d731a32010-04-29 01:04:069066 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:239067 {
9068 "", // unused
9069 "http://www.example.org/direct",
9070 "www.example.org:80",
9071 false,
9072 },
9073 {
9074 "", // unused
9075 "http://[2001:1418:13:1::25]/direct",
9076 "[2001:1418:13:1::25]:80",
9077 false,
9078 },
[email protected]04e5be32009-06-26 20:00:319079
bncce36dca22015-04-21 22:11:239080 // SSL Tests
9081 {
9082 "", // unused
9083 "https://www.example.org/direct_ssl",
9084 "ssl/www.example.org:443",
9085 true,
9086 },
9087 {
9088 "", // unused
9089 "https://[2001:1418:13:1::25]/direct",
9090 "ssl/[2001:1418:13:1::25]:443",
9091 true,
9092 },
9093 {
9094 "", // unused
bncaa60ff402016-06-22 19:12:429095 "https://host.with.alternate/direct",
bncce36dca22015-04-21 22:11:239096 "ssl/host.with.alternate:443",
9097 true,
9098 },
[email protected]2d731a32010-04-29 01:04:069099 };
[email protected]2ff8b312010-04-26 22:20:549100
viettrungluue4a8b882014-10-16 06:17:389101 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:039102 session_deps_.proxy_service =
9103 ProxyService::CreateFixed(tests[i].proxy_server);
danakj1fd259a02016-04-16 03:17:099104 std::unique_ptr<HttpNetworkSession> session(
bnca9b9e222016-07-11 20:10:409105 SetupSessionForGroupNameTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:069106
mmenkee65e7af2015-10-13 17:16:429107 HttpNetworkSessionPeer peer(session.get());
[email protected]ab739042011-04-07 15:22:289108 CaptureGroupNameTransportSocketPool* transport_conn_pool =
9109 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:139110 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:349111 new CaptureGroupNameSSLSocketPool(NULL, NULL);
danakj1fd259a02016-04-16 03:17:099112 std::unique_ptr<MockClientSocketPoolManager> mock_pool_manager(
[email protected]831e4a32013-11-14 02:14:449113 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:029114 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
9115 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:489116 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:069117
9118 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:429119 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:189120 if (tests[i].ssl)
9121 EXPECT_EQ(tests[i].expected_group_name,
9122 ssl_conn_pool->last_group_name_received());
9123 else
9124 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:289125 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:069126 }
[email protected]2d731a32010-04-29 01:04:069127}
9128
bncd16676a2016-07-20 16:23:019129TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
[email protected]2d731a32010-04-29 01:04:069130 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:239131 {
9132 "http_proxy",
9133 "http://www.example.org/http_proxy_normal",
9134 "www.example.org:80",
9135 false,
9136 },
[email protected]2d731a32010-04-29 01:04:069137
bncce36dca22015-04-21 22:11:239138 // SSL Tests
9139 {
9140 "http_proxy",
9141 "https://www.example.org/http_connect_ssl",
9142 "ssl/www.example.org:443",
9143 true,
9144 },
[email protected]af3490e2010-10-16 21:02:299145
bncce36dca22015-04-21 22:11:239146 {
9147 "http_proxy",
bncaa60ff402016-06-22 19:12:429148 "https://host.with.alternate/direct",
bncce36dca22015-04-21 22:11:239149 "ssl/host.with.alternate:443",
9150 true,
9151 },
[email protected]45499252013-01-23 17:12:569152
bncce36dca22015-04-21 22:11:239153 {
9154 "http_proxy",
9155 "ftp://ftp.google.com/http_proxy_normal",
9156 "ftp/ftp.google.com:21",
9157 false,
9158 },
[email protected]2d731a32010-04-29 01:04:069159 };
9160
viettrungluue4a8b882014-10-16 06:17:389161 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:039162 session_deps_.proxy_service =
9163 ProxyService::CreateFixed(tests[i].proxy_server);
danakj1fd259a02016-04-16 03:17:099164 std::unique_ptr<HttpNetworkSession> session(
bnca9b9e222016-07-11 20:10:409165 SetupSessionForGroupNameTests(&session_deps_));
[email protected]2d731a32010-04-29 01:04:069166
mmenkee65e7af2015-10-13 17:16:429167 HttpNetworkSessionPeer peer(session.get());
[email protected]2d731a32010-04-29 01:04:069168
[email protected]e60e47a2010-07-14 03:37:189169 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:139170 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:349171 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:139172 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:349173 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:029174
danakj1fd259a02016-04-16 03:17:099175 std::unique_ptr<MockClientSocketPoolManager> mock_pool_manager(
[email protected]831e4a32013-11-14 02:14:449176 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:029177 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
9178 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:489179 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]2d731a32010-04-29 01:04:069180
9181 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:429182 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:189183 if (tests[i].ssl)
9184 EXPECT_EQ(tests[i].expected_group_name,
9185 ssl_conn_pool->last_group_name_received());
9186 else
9187 EXPECT_EQ(tests[i].expected_group_name,
9188 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:069189 }
[email protected]2d731a32010-04-29 01:04:069190}
9191
bncd16676a2016-07-20 16:23:019192TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
[email protected]2d731a32010-04-29 01:04:069193 const GroupNameTest tests[] = {
bncce36dca22015-04-21 22:11:239194 {
9195 "socks4://socks_proxy:1080",
9196 "http://www.example.org/socks4_direct",
9197 "socks4/www.example.org:80",
9198 false,
9199 },
9200 {
9201 "socks5://socks_proxy:1080",
9202 "http://www.example.org/socks5_direct",
9203 "socks5/www.example.org:80",
9204 false,
9205 },
[email protected]2d731a32010-04-29 01:04:069206
bncce36dca22015-04-21 22:11:239207 // SSL Tests
9208 {
9209 "socks4://socks_proxy:1080",
9210 "https://www.example.org/socks4_ssl",
9211 "socks4/ssl/www.example.org:443",
9212 true,
9213 },
9214 {
9215 "socks5://socks_proxy:1080",
9216 "https://www.example.org/socks5_ssl",
9217 "socks5/ssl/www.example.org:443",
9218 true,
9219 },
[email protected]af3490e2010-10-16 21:02:299220
bncce36dca22015-04-21 22:11:239221 {
9222 "socks4://socks_proxy:1080",
bncaa60ff402016-06-22 19:12:429223 "https://host.with.alternate/direct",
bncce36dca22015-04-21 22:11:239224 "socks4/ssl/host.with.alternate:443",
9225 true,
9226 },
[email protected]04e5be32009-06-26 20:00:319227 };
9228
viettrungluue4a8b882014-10-16 06:17:389229 for (size_t i = 0; i < arraysize(tests); ++i) {
rdsmith82957ad2015-09-16 19:42:039230 session_deps_.proxy_service =
9231 ProxyService::CreateFixed(tests[i].proxy_server);
danakj1fd259a02016-04-16 03:17:099232 std::unique_ptr<HttpNetworkSession> session(
bnca9b9e222016-07-11 20:10:409233 SetupSessionForGroupNameTests(&session_deps_));
[email protected]8b114dd72011-03-25 05:33:029234
mmenkee65e7af2015-10-13 17:16:429235 HttpNetworkSessionPeer peer(session.get());
[email protected]04e5be32009-06-26 20:00:319236
[email protected]e60e47a2010-07-14 03:37:189237 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:139238 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:349239 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:139240 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:349241 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:029242
danakj1fd259a02016-04-16 03:17:099243 std::unique_ptr<MockClientSocketPoolManager> mock_pool_manager(
[email protected]831e4a32013-11-14 02:14:449244 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:029245 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
9246 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
dchengc7eeda422015-12-26 03:56:489247 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]04e5be32009-06-26 20:00:319248
danakj1fd259a02016-04-16 03:17:099249 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509250 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]04e5be32009-06-26 20:00:319251
[email protected]2d731a32010-04-29 01:04:069252 EXPECT_EQ(ERR_IO_PENDING,
mmenkee65e7af2015-10-13 17:16:429253 GroupNameTransactionHelper(tests[i].url, session.get()));
[email protected]e60e47a2010-07-14 03:37:189254 if (tests[i].ssl)
9255 EXPECT_EQ(tests[i].expected_group_name,
9256 ssl_conn_pool->last_group_name_received());
9257 else
9258 EXPECT_EQ(tests[i].expected_group_name,
9259 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:319260 }
9261}
9262
bncd16676a2016-07-20 16:23:019263TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:279264 HttpRequestInfo request;
9265 request.method = "GET";
bncce36dca22015-04-21 22:11:239266 request.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:279267
rdsmith82957ad2015-09-16 19:42:039268 session_deps_.proxy_service =
9269 ProxyService::CreateFixed("myproxy:70;foobar:80");
[email protected]b59ff372009-07-15 22:04:329270
[email protected]69719062010-01-05 20:09:219271 // This simulates failure resolving all hostnames; that means we will fail
9272 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]bb88e1d32013-05-03 23:11:079273 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
[email protected]b59ff372009-07-15 22:04:329274
danakj1fd259a02016-04-16 03:17:099275 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9276 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419277 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]9172a982009-06-06 00:30:259278
[email protected]49639fa2011-12-20 23:22:419279 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:259280
[email protected]49639fa2011-12-20 23:22:419281 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019282 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9172a982009-06-06 00:30:259283
[email protected]9172a982009-06-06 00:30:259284 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019285 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]9172a982009-06-06 00:30:259286}
9287
[email protected]685af592010-05-11 19:31:249288// Base test to make sure that when the load flags for a request specify to
9289// bypass the cache, the DNS cache is not used.
[email protected]23e482282013-06-14 16:08:029290void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
[email protected]bb88e1d32013-05-03 23:11:079291 int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:279292 // Issue a request, asking to bypass the cache(s).
maksim.sisov31452af2016-07-27 06:38:109293 HttpRequestInfo request_info;
9294 request_info.method = "GET";
9295 request_info.load_flags = load_flags;
9296 request_info.url = GURL("http://www.example.org/");
[email protected]cb9bf6ca2011-01-28 13:15:279297
[email protected]a2c2fb92009-07-18 07:31:049298 // Select a host resolver that does caching.
[email protected]bb88e1d32013-05-03 23:11:079299 session_deps_.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:329300
danakj1fd259a02016-04-16 03:17:099301 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9302 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419303 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]3b9cca42009-06-16 01:08:289304
bncce36dca22015-04-21 22:11:239305 // Warm up the host cache so it has an entry for "www.example.org".
[email protected]3b9cca42009-06-16 01:08:289306 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:299307 TestCompletionCallback callback;
maksim.sisov31452af2016-07-27 06:38:109308 std::unique_ptr<HostResolver::Request> request1;
[email protected]bb88e1d32013-05-03 23:11:079309 int rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:239310 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
maksim.sisov31452af2016-07-27 06:38:109311 DEFAULT_PRIORITY, &addrlist, callback.callback(), &request1,
9312 BoundNetLog());
robpercival214763f2016-07-01 23:27:019313 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6e78dfb2011-07-28 21:34:479314 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019315 EXPECT_THAT(rv, IsOk());
[email protected]3b9cca42009-06-16 01:08:289316
9317 // Verify that it was added to host cache, by doing a subsequent async lookup
9318 // and confirming it completes synchronously.
maksim.sisov31452af2016-07-27 06:38:109319 std::unique_ptr<HostResolver::Request> request2;
[email protected]bb88e1d32013-05-03 23:11:079320 rv = session_deps_.host_resolver->Resolve(
bncce36dca22015-04-21 22:11:239321 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
maksim.sisov31452af2016-07-27 06:38:109322 DEFAULT_PRIORITY, &addrlist, callback.callback(), &request2,
9323 BoundNetLog());
robpercival214763f2016-07-01 23:27:019324 ASSERT_THAT(rv, IsOk());
[email protected]3b9cca42009-06-16 01:08:289325
bncce36dca22015-04-21 22:11:239326 // Inject a failure the next time that "www.example.org" is resolved. This way
[email protected]3b9cca42009-06-16 01:08:289327 // we can tell if the next lookup hit the cache, or the "network".
9328 // (cache --> success, "network" --> failure).
bncce36dca22015-04-21 22:11:239329 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.example.org");
[email protected]3b9cca42009-06-16 01:08:289330
9331 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
9332 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:069333 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:399334 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079335 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:289336
[email protected]3b9cca42009-06-16 01:08:289337 // Run the request.
maksim.sisov31452af2016-07-27 06:38:109338 rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019339 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]49639fa2011-12-20 23:22:419340 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:289341
9342 // If we bypassed the cache, we would have gotten a failure while resolving
bncce36dca22015-04-21 22:11:239343 // "www.example.org".
robpercival214763f2016-07-01 23:27:019344 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]3b9cca42009-06-16 01:08:289345}
9346
[email protected]685af592010-05-11 19:31:249347// There are multiple load flags that should trigger the host cache bypass.
9348// Test each in isolation:
bncd16676a2016-07-20 16:23:019349TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
[email protected]685af592010-05-11 19:31:249350 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
9351}
9352
bncd16676a2016-07-20 16:23:019353TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
[email protected]685af592010-05-11 19:31:249354 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
9355}
9356
bncd16676a2016-07-20 16:23:019357TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
[email protected]685af592010-05-11 19:31:249358 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
9359}
9360
[email protected]0877e3d2009-10-17 22:29:579361// Make sure we can handle an error when writing the request.
bncd16676a2016-07-20 16:23:019362TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
[email protected]0877e3d2009-10-17 22:29:579363 HttpRequestInfo request;
9364 request.method = "GET";
9365 request.url = GURL("http://www.foo.com/");
9366 request.load_flags = 0;
9367
9368 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:069369 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579370 };
[email protected]31a2bfe2010-02-09 08:03:399371 StaticSocketDataProvider data(NULL, 0,
9372 write_failure, arraysize(write_failure));
[email protected]bb88e1d32013-05-03 23:11:079373 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:099374 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579375
[email protected]49639fa2011-12-20 23:22:419376 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579377
danakj1fd259a02016-04-16 03:17:099378 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419379 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579380
[email protected]49639fa2011-12-20 23:22:419381 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019382 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:579383
9384 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019385 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
ttuttled9dbc652015-09-29 20:00:599386
9387 IPEndPoint endpoint;
9388 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9389 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579390}
9391
zmo9528c9f42015-08-04 22:12:089392// Check that a connection closed after the start of the headers finishes ok.
bncd16676a2016-07-20 16:23:019393TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
[email protected]0877e3d2009-10-17 22:29:579394 HttpRequestInfo request;
9395 request.method = "GET";
9396 request.url = GURL("http://www.foo.com/");
9397 request.load_flags = 0;
9398
9399 MockRead data_reads[] = {
9400 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:069401 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579402 };
9403
[email protected]31a2bfe2010-02-09 08:03:399404 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079405 session_deps_.socket_factory->AddSocketDataProvider(&data);
danakj1fd259a02016-04-16 03:17:099406 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579407
[email protected]49639fa2011-12-20 23:22:419408 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579409
danakj1fd259a02016-04-16 03:17:099410 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419411 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579412
[email protected]49639fa2011-12-20 23:22:419413 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019414 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:579415
9416 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019417 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:089418
9419 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529420 ASSERT_TRUE(response);
zmo9528c9f42015-08-04 22:12:089421
wezca1070932016-05-26 20:30:529422 EXPECT_TRUE(response->headers);
zmo9528c9f42015-08-04 22:12:089423 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9424
9425 std::string response_data;
9426 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019427 EXPECT_THAT(rv, IsOk());
zmo9528c9f42015-08-04 22:12:089428 EXPECT_EQ("", response_data);
ttuttled9dbc652015-09-29 20:00:599429
9430 IPEndPoint endpoint;
9431 EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
9432 EXPECT_LT(0u, endpoint.address().size());
[email protected]0877e3d2009-10-17 22:29:579433}
9434
9435// Make sure that a dropped connection while draining the body for auth
9436// restart does the right thing.
bncd16676a2016-07-20 16:23:019437TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
[email protected]0877e3d2009-10-17 22:29:579438 HttpRequestInfo request;
9439 request.method = "GET";
bncce36dca22015-04-21 22:11:239440 request.url = GURL("http://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579441 request.load_flags = 0;
9442
9443 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239444 MockWrite(
9445 "GET / HTTP/1.1\r\n"
9446 "Host: www.example.org\r\n"
9447 "Connection: keep-alive\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579448 };
9449
9450 MockRead data_reads1[] = {
9451 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
9452 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
9453 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9454 MockRead("Content-Length: 14\r\n\r\n"),
9455 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:069456 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:579457 };
9458
[email protected]31a2bfe2010-02-09 08:03:399459 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9460 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:079461 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:579462
9463 // After calling trans->RestartWithAuth(), this is the request we should
9464 // be issuing -- the final header line contains the credentials.
9465 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239466 MockWrite(
9467 "GET / HTTP/1.1\r\n"
9468 "Host: www.example.org\r\n"
9469 "Connection: keep-alive\r\n"
9470 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]0877e3d2009-10-17 22:29:579471 };
9472
9473 // Lastly, the server responds with the actual content.
9474 MockRead data_reads2[] = {
9475 MockRead("HTTP/1.1 200 OK\r\n"),
9476 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9477 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069478 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:579479 };
9480
[email protected]31a2bfe2010-02-09 08:03:399481 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9482 data_writes2, arraysize(data_writes2));
[email protected]bb88e1d32013-05-03 23:11:079483 session_deps_.socket_factory->AddSocketDataProvider(&data2);
danakj1fd259a02016-04-16 03:17:099484 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]0877e3d2009-10-17 22:29:579485
[email protected]49639fa2011-12-20 23:22:419486 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:579487
danakj1fd259a02016-04-16 03:17:099488 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:509489 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509490
[email protected]49639fa2011-12-20 23:22:419491 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019492 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:579493
9494 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019495 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:579496
9497 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529498 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:049499 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:579500
[email protected]49639fa2011-12-20 23:22:419501 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:579502
[email protected]49639fa2011-12-20 23:22:419503 rv = trans->RestartWithAuth(
9504 AuthCredentials(kFoo, kBar), callback2.callback());
robpercival214763f2016-07-01 23:27:019505 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:579506
9507 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019508 EXPECT_THAT(rv, IsOk());
[email protected]0877e3d2009-10-17 22:29:579509
9510 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529511 ASSERT_TRUE(response);
9512 EXPECT_FALSE(response->auth_challenge);
[email protected]0877e3d2009-10-17 22:29:579513 EXPECT_EQ(100, response->headers->GetContentLength());
9514}
9515
9516// Test HTTPS connections going through a proxy that sends extra data.
bncd16676a2016-07-20 16:23:019517TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
rdsmith82957ad2015-09-16 19:42:039518 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
[email protected]0877e3d2009-10-17 22:29:579519
9520 HttpRequestInfo request;
9521 request.method = "GET";
bncce36dca22015-04-21 22:11:239522 request.url = GURL("https://www.example.org/");
[email protected]0877e3d2009-10-17 22:29:579523 request.load_flags = 0;
9524
9525 MockRead proxy_reads[] = {
9526 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:069527 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:579528 };
9529
[email protected]31a2bfe2010-02-09 08:03:399530 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:069531 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:579532
[email protected]bb88e1d32013-05-03 23:11:079533 session_deps_.socket_factory->AddSocketDataProvider(&data);
9534 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:579535
[email protected]49639fa2011-12-20 23:22:419536 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:579537
[email protected]bb88e1d32013-05-03 23:11:079538 session_deps_.socket_factory->ResetNextMockIndexes();
[email protected]0877e3d2009-10-17 22:29:579539
danakj1fd259a02016-04-16 03:17:099540 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9541 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419542 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0877e3d2009-10-17 22:29:579543
[email protected]49639fa2011-12-20 23:22:419544 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]0877e3d2009-10-17 22:29:579546
9547 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019548 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
[email protected]0877e3d2009-10-17 22:29:579549}
9550
bncd16676a2016-07-20 16:23:019551TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:469552 HttpRequestInfo request;
9553 request.method = "GET";
bncce36dca22015-04-21 22:11:239554 request.url = GURL("http://www.example.org/");
[email protected]9492e4a2010-02-24 00:58:469555 request.load_flags = 0;
9556
danakj1fd259a02016-04-16 03:17:099557 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9558 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419559 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:279560
[email protected]e22e1362009-11-23 21:31:129561 MockRead data_reads[] = {
9562 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:069563 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:129564 };
[email protected]9492e4a2010-02-24 00:58:469565
9566 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079567 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]9492e4a2010-02-24 00:58:469568
[email protected]49639fa2011-12-20 23:22:419569 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:469570
[email protected]49639fa2011-12-20 23:22:419571 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019572 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]9492e4a2010-02-24 00:58:469573
robpercival214763f2016-07-01 23:27:019574 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]9492e4a2010-02-24 00:58:469575
9576 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529577 ASSERT_TRUE(response);
[email protected]9492e4a2010-02-24 00:58:469578
wezca1070932016-05-26 20:30:529579 EXPECT_TRUE(response->headers);
[email protected]9492e4a2010-02-24 00:58:469580 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
9581
9582 std::string response_data;
9583 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:019584 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
[email protected]e22e1362009-11-23 21:31:129585}
9586
bncd16676a2016-07-20 16:23:019587TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]6cdfd7f2013-02-08 20:40:159588 base::FilePath temp_file_path;
[email protected]03d9afc02013-12-03 17:55:529589 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
avibf0746c2015-12-09 19:53:149590 const uint64_t kFakeSize = 100000; // file is actually blank
[email protected]d98961652012-09-11 20:27:219591 UploadFileElementReader::ScopedOverridingContentLengthForTests
9592 overriding_content_length(kFakeSize);
[email protected]95d88ffe2010-02-04 21:25:339593
danakj1fd259a02016-04-16 03:17:099594 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
9595 element_readers.push_back(base::WrapUnique(new UploadFileElementReader(
avibf0746c2015-12-09 19:53:149596 base::ThreadTaskRunnerHandle::Get().get(), temp_file_path, 0,
9597 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229598 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279599
9600 HttpRequestInfo request;
9601 request.method = "POST";
bncce36dca22015-04-21 22:11:239602 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279603 request.upload_data_stream = &upload_data_stream;
9604 request.load_flags = 0;
9605
danakj1fd259a02016-04-16 03:17:099606 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9607 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419608 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]95d88ffe2010-02-04 21:25:339609
9610 MockRead data_reads[] = {
9611 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9612 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069613 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:339614 };
[email protected]31a2bfe2010-02-09 08:03:399615 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079616 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]95d88ffe2010-02-04 21:25:339617
[email protected]49639fa2011-12-20 23:22:419618 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:339619
[email protected]49639fa2011-12-20 23:22:419620 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019621 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]95d88ffe2010-02-04 21:25:339622
9623 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019624 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
[email protected]95d88ffe2010-02-04 21:25:339625
9626 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529627 ASSERT_TRUE(response);
[email protected]95d88ffe2010-02-04 21:25:339628
maksim.sisove869bf52016-06-23 17:11:529629 EXPECT_FALSE(response->headers);
[email protected]95d88ffe2010-02-04 21:25:339630
[email protected]dd3aa792013-07-16 19:10:239631 base::DeleteFile(temp_file_path, false);
[email protected]95d88ffe2010-02-04 21:25:339632}
9633
bncd16676a2016-07-20 16:23:019634TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]6cdfd7f2013-02-08 20:40:159635 base::FilePath temp_file;
[email protected]03d9afc02013-12-03 17:55:529636 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
[email protected]6624b4622010-03-29 19:58:369637 std::string temp_file_content("Unreadable file.");
[email protected]e5c2a22e2014-03-06 20:42:309638 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
[email protected]6624b4622010-03-29 19:58:369639 temp_file_content.length()));
[email protected]92be8eb2014-08-07 22:57:119640 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
[email protected]6624b4622010-03-29 19:58:369641
danakj1fd259a02016-04-16 03:17:099642 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
9643 element_readers.push_back(base::WrapUnique(new UploadFileElementReader(
avibf0746c2015-12-09 19:53:149644 base::ThreadTaskRunnerHandle::Get().get(), temp_file, 0,
9645 std::numeric_limits<uint64_t>::max(), base::Time())));
olli.raula6df48b2a2015-11-26 07:40:229646 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]329b68b2012-11-14 17:54:279647
9648 HttpRequestInfo request;
9649 request.method = "POST";
bncce36dca22015-04-21 22:11:239650 request.url = GURL("http://www.example.org/upload");
[email protected]329b68b2012-11-14 17:54:279651 request.upload_data_stream = &upload_data_stream;
9652 request.load_flags = 0;
9653
[email protected]999dd8c2013-11-12 06:45:549654 // If we try to upload an unreadable file, the transaction should fail.
danakj1fd259a02016-04-16 03:17:099655 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9656 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419657 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]6624b4622010-03-29 19:58:369658
[email protected]999dd8c2013-11-12 06:45:549659 StaticSocketDataProvider data(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:079660 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]6624b4622010-03-29 19:58:369661
[email protected]49639fa2011-12-20 23:22:419662 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:369663
[email protected]49639fa2011-12-20 23:22:419664 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019665 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6624b4622010-03-29 19:58:369666
9667 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:019668 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
[email protected]6624b4622010-03-29 19:58:369669
[email protected]dd3aa792013-07-16 19:10:239670 base::DeleteFile(temp_file, false);
[email protected]6624b4622010-03-29 19:58:369671}
9672
bncd16676a2016-07-20 16:23:019673TEST_F(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
[email protected]02cad5d2013-10-02 08:14:039674 class FakeUploadElementReader : public UploadElementReader {
9675 public:
9676 FakeUploadElementReader() {}
dchengb03027d2014-10-21 12:00:209677 ~FakeUploadElementReader() override {}
[email protected]02cad5d2013-10-02 08:14:039678
9679 const CompletionCallback& callback() const { return callback_; }
9680
9681 // UploadElementReader overrides:
dchengb03027d2014-10-21 12:00:209682 int Init(const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039683 callback_ = callback;
9684 return ERR_IO_PENDING;
9685 }
avibf0746c2015-12-09 19:53:149686 uint64_t GetContentLength() const override { return 0; }
9687 uint64_t BytesRemaining() const override { return 0; }
dchengb03027d2014-10-21 12:00:209688 int Read(IOBuffer* buf,
9689 int buf_length,
9690 const CompletionCallback& callback) override {
[email protected]02cad5d2013-10-02 08:14:039691 return ERR_FAILED;
9692 }
9693
9694 private:
9695 CompletionCallback callback_;
9696 };
9697
9698 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
danakj1fd259a02016-04-16 03:17:099699 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
9700 element_readers.push_back(base::WrapUnique(fake_reader));
olli.raula6df48b2a2015-11-26 07:40:229701 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02cad5d2013-10-02 08:14:039702
9703 HttpRequestInfo request;
9704 request.method = "POST";
bncce36dca22015-04-21 22:11:239705 request.url = GURL("http://www.example.org/upload");
[email protected]02cad5d2013-10-02 08:14:039706 request.upload_data_stream = &upload_data_stream;
9707 request.load_flags = 0;
9708
danakj1fd259a02016-04-16 03:17:099709 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9710 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419711 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02cad5d2013-10-02 08:14:039712
9713 StaticSocketDataProvider data;
9714 session_deps_.socket_factory->AddSocketDataProvider(&data);
9715
9716 TestCompletionCallback callback;
9717 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019718 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
fdoray92e35a72016-06-10 15:54:559719 base::RunLoop().RunUntilIdle();
[email protected]02cad5d2013-10-02 08:14:039720
9721 // Transaction is pending on request body initialization.
9722 ASSERT_FALSE(fake_reader->callback().is_null());
9723
9724 // Return Init()'s result after the transaction gets destroyed.
9725 trans.reset();
9726 fake_reader->callback().Run(OK); // Should not crash.
9727}
9728
[email protected]aeefc9e82010-02-19 16:18:279729// Tests that changes to Auth realms are treated like auth rejections.
bncd16676a2016-07-20 16:23:019730TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
[email protected]aeefc9e82010-02-19 16:18:279731 HttpRequestInfo request;
9732 request.method = "GET";
bncce36dca22015-04-21 22:11:239733 request.url = GURL("http://www.example.org/");
[email protected]aeefc9e82010-02-19 16:18:279734 request.load_flags = 0;
9735
9736 // First transaction will request a resource and receive a Basic challenge
9737 // with realm="first_realm".
9738 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:239739 MockWrite(
9740 "GET / HTTP/1.1\r\n"
9741 "Host: www.example.org\r\n"
9742 "Connection: keep-alive\r\n"
9743 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279744 };
9745 MockRead data_reads1[] = {
9746 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9747 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9748 "\r\n"),
9749 };
9750
9751 // After calling trans->RestartWithAuth(), provide an Authentication header
9752 // for first_realm. The server will reject and provide a challenge with
9753 // second_realm.
9754 MockWrite data_writes2[] = {
bncce36dca22015-04-21 22:11:239755 MockWrite(
9756 "GET / HTTP/1.1\r\n"
9757 "Host: www.example.org\r\n"
9758 "Connection: keep-alive\r\n"
9759 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
9760 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279761 };
9762 MockRead data_reads2[] = {
9763 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9764 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
9765 "\r\n"),
9766 };
9767
9768 // This again fails, and goes back to first_realm. Make sure that the
9769 // entry is removed from cache.
9770 MockWrite data_writes3[] = {
bncce36dca22015-04-21 22:11:239771 MockWrite(
9772 "GET / HTTP/1.1\r\n"
9773 "Host: www.example.org\r\n"
9774 "Connection: keep-alive\r\n"
9775 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
9776 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279777 };
9778 MockRead data_reads3[] = {
9779 MockRead("HTTP/1.1 401 Unauthorized\r\n"
9780 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
9781 "\r\n"),
9782 };
9783
9784 // Try one last time (with the correct password) and get the resource.
9785 MockWrite data_writes4[] = {
bncce36dca22015-04-21 22:11:239786 MockWrite(
9787 "GET / HTTP/1.1\r\n"
9788 "Host: www.example.org\r\n"
9789 "Connection: keep-alive\r\n"
9790 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
9791 "\r\n"),
[email protected]aeefc9e82010-02-19 16:18:279792 };
9793 MockRead data_reads4[] = {
9794 MockRead("HTTP/1.1 200 OK\r\n"
9795 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:509796 "Content-Length: 5\r\n"
9797 "\r\n"
9798 "hello"),
[email protected]aeefc9e82010-02-19 16:18:279799 };
9800
9801 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9802 data_writes1, arraysize(data_writes1));
9803 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9804 data_writes2, arraysize(data_writes2));
9805 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
9806 data_writes3, arraysize(data_writes3));
9807 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
9808 data_writes4, arraysize(data_writes4));
[email protected]bb88e1d32013-05-03 23:11:079809 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9810 session_deps_.socket_factory->AddSocketDataProvider(&data2);
9811 session_deps_.socket_factory->AddSocketDataProvider(&data3);
9812 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]aeefc9e82010-02-19 16:18:279813
[email protected]49639fa2011-12-20 23:22:419814 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:279815
danakj1fd259a02016-04-16 03:17:099816 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9817 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:419818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:509819
[email protected]aeefc9e82010-02-19 16:18:279820 // Issue the first request with Authorize headers. There should be a
9821 // password prompt for first_realm waiting to be filled in after the
9822 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419823 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019824 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:279825 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:019826 EXPECT_THAT(rv, IsOk());
[email protected]aeefc9e82010-02-19 16:18:279827 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529828 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:049829 const AuthChallengeInfo* challenge = response->auth_challenge.get();
wezca1070932016-05-26 20:30:529830 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:049831 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:439832 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049833 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199834 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279835
9836 // Issue the second request with an incorrect password. There should be a
9837 // password prompt for second_realm waiting to be filled in after the
9838 // transaction completes.
[email protected]49639fa2011-12-20 23:22:419839 TestCompletionCallback callback2;
9840 rv = trans->RestartWithAuth(
9841 AuthCredentials(kFirst, kBaz), callback2.callback());
robpercival214763f2016-07-01 23:27:019842 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:279843 rv = callback2.WaitForResult();
robpercival214763f2016-07-01 23:27:019844 EXPECT_THAT(rv, IsOk());
[email protected]aeefc9e82010-02-19 16:18:279845 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529846 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:049847 challenge = response->auth_challenge.get();
wezca1070932016-05-26 20:30:529848 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:049849 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:439850 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049851 EXPECT_EQ("second_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199852 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279853
9854 // Issue the third request with another incorrect password. There should be
9855 // a password prompt for first_realm waiting to be filled in. If the password
9856 // prompt is not present, it indicates that the HttpAuthCacheEntry for
9857 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:419858 TestCompletionCallback callback3;
9859 rv = trans->RestartWithAuth(
9860 AuthCredentials(kSecond, kFou), callback3.callback());
robpercival214763f2016-07-01 23:27:019861 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:279862 rv = callback3.WaitForResult();
robpercival214763f2016-07-01 23:27:019863 EXPECT_THAT(rv, IsOk());
[email protected]aeefc9e82010-02-19 16:18:279864 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529865 ASSERT_TRUE(response);
[email protected]79cb5c12011-09-12 13:12:049866 challenge = response->auth_challenge.get();
wezca1070932016-05-26 20:30:529867 ASSERT_TRUE(challenge);
[email protected]79cb5c12011-09-12 13:12:049868 EXPECT_FALSE(challenge->is_proxy);
asanka098c0092016-06-16 20:18:439869 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
[email protected]79cb5c12011-09-12 13:12:049870 EXPECT_EQ("first_realm", challenge->realm);
aberentbba302d2015-12-03 10:20:199871 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:279872
9873 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:419874 TestCompletionCallback callback4;
9875 rv = trans->RestartWithAuth(
9876 AuthCredentials(kFirst, kBar), callback4.callback());
robpercival214763f2016-07-01 23:27:019877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]aeefc9e82010-02-19 16:18:279878 rv = callback4.WaitForResult();
robpercival214763f2016-07-01 23:27:019879 EXPECT_THAT(rv, IsOk());
[email protected]aeefc9e82010-02-19 16:18:279880 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529881 ASSERT_TRUE(response);
9882 EXPECT_FALSE(response->auth_challenge);
[email protected]aeefc9e82010-02-19 16:18:279883}
9884
bncd16676a2016-07-20 16:23:019885TEST_F(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
bncc958faa2015-07-31 18:14:529886 MockRead data_reads[] = {
9887 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:439888 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:529889 MockRead("\r\n"),
9890 MockRead("hello world"),
9891 MockRead(SYNCHRONOUS, OK),
9892 };
9893
9894 HttpRequestInfo request;
9895 request.method = "GET";
bncb26024382016-06-29 02:39:459896 request.url = GURL("https://www.example.org/");
bncc958faa2015-07-31 18:14:529897 request.load_flags = 0;
9898
9899 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
bncc958faa2015-07-31 18:14:529900 session_deps_.socket_factory->AddSocketDataProvider(&data);
9901
bncb26024382016-06-29 02:39:459902 SSLSocketDataProvider ssl(ASYNC, OK);
9903 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9904
bncc958faa2015-07-31 18:14:529905 TestCompletionCallback callback;
9906
danakj1fd259a02016-04-16 03:17:099907 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9908 std::unique_ptr<HttpTransaction> trans(
bncc958faa2015-07-31 18:14:529909 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9910
9911 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019912 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:529913
bncb26024382016-06-29 02:39:459914 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:409915 HttpServerProperties* http_server_properties =
9916 session->http_server_properties();
bncc958faa2015-07-31 18:14:529917 AlternativeServiceVector alternative_service_vector =
bnc525e175a2016-06-20 12:36:409918 http_server_properties->GetAlternativeServices(test_server);
bncc958faa2015-07-31 18:14:529919 EXPECT_TRUE(alternative_service_vector.empty());
9920
robpercival214763f2016-07-01 23:27:019921 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:529922
9923 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:529924 ASSERT_TRUE(response);
9925 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:529926 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9927 EXPECT_FALSE(response->was_fetched_via_spdy);
9928 EXPECT_FALSE(response->was_npn_negotiated);
9929
9930 std::string response_data;
robpercival214763f2016-07-01 23:27:019931 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
bncc958faa2015-07-31 18:14:529932 EXPECT_EQ("hello world", response_data);
9933
9934 alternative_service_vector =
bnc525e175a2016-06-20 12:36:409935 http_server_properties->GetAlternativeServices(test_server);
bncc958faa2015-07-31 18:14:529936 ASSERT_EQ(1u, alternative_service_vector.size());
bnca9b9e222016-07-11 20:10:409937 EXPECT_EQ(AlternateProtocolFromNextProto(kProtoHTTP2),
bncc958faa2015-07-31 18:14:529938 alternative_service_vector[0].protocol);
bncb26024382016-06-29 02:39:459939 EXPECT_EQ("mail.example.org", alternative_service_vector[0].host);
bncc958faa2015-07-31 18:14:529940 EXPECT_EQ(443, alternative_service_vector[0].port);
9941}
9942
bnce3dd56f2016-06-01 10:37:119943// Regression test for https://crbug.com/615497.
bncd16676a2016-07-20 16:23:019944TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:119945 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
bnce3dd56f2016-06-01 10:37:119946 MockRead data_reads[] = {
9947 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:439948 MockRead(kAlternativeServiceHttpHeader),
bnce3dd56f2016-06-01 10:37:119949 MockRead("\r\n"),
9950 MockRead("hello world"),
9951 MockRead(SYNCHRONOUS, OK),
9952 };
9953
9954 HttpRequestInfo request;
9955 request.method = "GET";
9956 request.url = GURL("http://www.example.org/");
9957 request.load_flags = 0;
9958
9959 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9960 session_deps_.socket_factory->AddSocketDataProvider(&data);
9961
9962 TestCompletionCallback callback;
9963
9964 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9965 std::unique_ptr<HttpTransaction> trans(
9966 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9967
9968 url::SchemeHostPort test_server(request.url);
bnc525e175a2016-06-20 12:36:409969 HttpServerProperties* http_server_properties =
9970 session->http_server_properties();
bnce3dd56f2016-06-01 10:37:119971 AlternativeServiceVector alternative_service_vector =
bnc525e175a2016-06-20 12:36:409972 http_server_properties->GetAlternativeServices(test_server);
bnce3dd56f2016-06-01 10:37:119973 EXPECT_TRUE(alternative_service_vector.empty());
9974
9975 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:019976 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9977 EXPECT_THAT(callback.WaitForResult(), IsOk());
bnce3dd56f2016-06-01 10:37:119978
9979 const HttpResponseInfo* response = trans->GetResponseInfo();
9980 ASSERT_TRUE(response);
9981 ASSERT_TRUE(response->headers);
9982 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9983 EXPECT_FALSE(response->was_fetched_via_spdy);
9984 EXPECT_FALSE(response->was_npn_negotiated);
9985
9986 std::string response_data;
robpercival214763f2016-07-01 23:27:019987 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
bnce3dd56f2016-06-01 10:37:119988 EXPECT_EQ("hello world", response_data);
9989
9990 alternative_service_vector =
bnc525e175a2016-06-20 12:36:409991 http_server_properties->GetAlternativeServices(test_server);
bnce3dd56f2016-06-01 10:37:119992 EXPECT_TRUE(alternative_service_vector.empty());
9993}
9994
bnc8bef8da22016-05-30 01:28:259995// HTTP/2 Alternative Services should be disabled if alternative service
9996// hostname is different from that of origin.
9997// TODO(bnc): Remove when https://crbug.com/615413 is fixed.
bncd16676a2016-07-20 16:23:019998TEST_F(HttpNetworkTransactionTest,
bnc8bef8da22016-05-30 01:28:259999 DisableHTTP2AlternativeServicesWithDifferentHost) {
bncb26024382016-06-29 02:39:4510000 session_deps_.enable_http2_alternative_service_with_different_host = false;
10001
bnc8bef8da22016-05-30 01:28:2510002 HttpRequestInfo request;
10003 request.method = "GET";
bncb26024382016-06-29 02:39:4510004 request.url = GURL("https://www.example.org/");
bnc8bef8da22016-05-30 01:28:2510005 request.load_flags = 0;
10006
10007 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10008 StaticSocketDataProvider first_data;
10009 first_data.set_connect_data(mock_connect);
10010 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4510011 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610012 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4510013 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
bnc8bef8da22016-05-30 01:28:2510014
10015 MockRead data_reads[] = {
10016 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
10017 MockRead(ASYNC, OK),
10018 };
10019 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads), NULL,
10020 0);
10021 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
10022
10023 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10024
bnc525e175a2016-06-20 12:36:4010025 HttpServerProperties* http_server_properties =
bnc8bef8da22016-05-30 01:28:2510026 session->http_server_properties();
10027 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010028 AlternateProtocolFromNextProto(kProtoHTTP2), "different.example.org",
bnc8bef8da22016-05-30 01:28:2510029 444);
10030 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10031 http_server_properties->SetAlternativeService(
10032 url::SchemeHostPort(request.url), alternative_service, expiration);
10033
10034 std::unique_ptr<HttpTransaction> trans(
10035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10036 TestCompletionCallback callback;
10037
10038 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10039 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0110040 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc8bef8da22016-05-30 01:28:2510041}
10042
bnce3dd56f2016-06-01 10:37:1110043// Regression test for https://crbug.com/615497:
10044// Alternative Services should be disabled for http origin.
bncd16676a2016-07-20 16:23:0110045TEST_F(HttpNetworkTransactionTest,
bnce3dd56f2016-06-01 10:37:1110046 DisableAlternativeServicesForInsecureOrigin) {
bnce3dd56f2016-06-01 10:37:1110047 HttpRequestInfo request;
10048 request.method = "GET";
10049 request.url = GURL("http://www.example.org/");
10050 request.load_flags = 0;
10051
10052 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10053 StaticSocketDataProvider first_data;
10054 first_data.set_connect_data(mock_connect);
10055 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
10056
10057 MockRead data_reads[] = {
10058 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
10059 MockRead(ASYNC, OK),
10060 };
10061 StaticSocketDataProvider second_data(data_reads, arraysize(data_reads), NULL,
10062 0);
10063 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
10064
10065 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10066
bnc525e175a2016-06-20 12:36:4010067 HttpServerProperties* http_server_properties =
bnce3dd56f2016-06-01 10:37:1110068 session->http_server_properties();
10069 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010070 AlternateProtocolFromNextProto(kProtoHTTP2), "", 444);
bnce3dd56f2016-06-01 10:37:1110071 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10072 http_server_properties->SetAlternativeService(
10073 url::SchemeHostPort(request.url), alternative_service, expiration);
10074
10075 std::unique_ptr<HttpTransaction> trans(
10076 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10077 TestCompletionCallback callback;
10078
10079 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10080 // Alternative service is not used, request fails.
robpercival214763f2016-07-01 23:27:0110081 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnce3dd56f2016-06-01 10:37:1110082}
10083
bncd16676a2016-07-20 16:23:0110084TEST_F(HttpNetworkTransactionTest, ClearAlternativeServices) {
bnc4f575852015-10-14 18:35:0810085 // Set an alternative service for origin.
danakj1fd259a02016-04-16 03:17:0910086 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4010087 HttpServerProperties* http_server_properties =
10088 session->http_server_properties();
bncb26024382016-06-29 02:39:4510089 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc4f575852015-10-14 18:35:0810090 AlternativeService alternative_service(QUIC, "", 80);
10091 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnc525e175a2016-06-20 12:36:4010092 http_server_properties->SetAlternativeService(
10093 test_server, alternative_service, expiration);
bnc4f575852015-10-14 18:35:0810094 AlternativeServiceVector alternative_service_vector =
bnc525e175a2016-06-20 12:36:4010095 http_server_properties->GetAlternativeServices(test_server);
bnc4f575852015-10-14 18:35:0810096 EXPECT_EQ(1u, alternative_service_vector.size());
10097
10098 // Send a clear header.
10099 MockRead data_reads[] = {
10100 MockRead("HTTP/1.1 200 OK\r\n"),
10101 MockRead("Alt-Svc: clear\r\n"),
10102 MockRead("\r\n"),
10103 MockRead("hello world"),
10104 MockRead(SYNCHRONOUS, OK),
10105 };
10106 StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
10107 session_deps_.socket_factory->AddSocketDataProvider(&data);
10108
bncb26024382016-06-29 02:39:4510109 SSLSocketDataProvider ssl(ASYNC, OK);
10110 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10111
bnc4f575852015-10-14 18:35:0810112 HttpRequestInfo request;
10113 request.method = "GET";
bncb26024382016-06-29 02:39:4510114 request.url = GURL("https://www.example.org/");
bnc4f575852015-10-14 18:35:0810115 request.load_flags = 0;
10116
10117 TestCompletionCallback callback;
10118
danakj1fd259a02016-04-16 03:17:0910119 std::unique_ptr<HttpTransaction> trans(
bnc4f575852015-10-14 18:35:0810120 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10121
10122 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110123 EXPECT_THAT(callback.GetResult(rv), IsOk());
bnc4f575852015-10-14 18:35:0810124
10125 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210126 ASSERT_TRUE(response);
10127 ASSERT_TRUE(response->headers);
bnc4f575852015-10-14 18:35:0810128 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10129 EXPECT_FALSE(response->was_fetched_via_spdy);
10130 EXPECT_FALSE(response->was_npn_negotiated);
10131
10132 std::string response_data;
robpercival214763f2016-07-01 23:27:0110133 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
bnc4f575852015-10-14 18:35:0810134 EXPECT_EQ("hello world", response_data);
10135
10136 alternative_service_vector =
bnc525e175a2016-06-20 12:36:4010137 http_server_properties->GetAlternativeServices(test_server);
bnc4f575852015-10-14 18:35:0810138 EXPECT_TRUE(alternative_service_vector.empty());
10139}
10140
bncd16676a2016-07-20 16:23:0110141TEST_F(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
bncc958faa2015-07-31 18:14:5210142 MockRead data_reads[] = {
10143 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4310144 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
10145 MockRead("h2=\":1234\"\r\n\r\n"),
bncc958faa2015-07-31 18:14:5210146 MockRead("hello world"),
10147 MockRead(SYNCHRONOUS, OK),
10148 };
10149
10150 HttpRequestInfo request;
10151 request.method = "GET";
bncb26024382016-06-29 02:39:4510152 request.url = GURL("https://www.example.org/");
bncc958faa2015-07-31 18:14:5210153 request.load_flags = 0;
10154
10155 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
bncc958faa2015-07-31 18:14:5210156 session_deps_.socket_factory->AddSocketDataProvider(&data);
10157
bncb26024382016-06-29 02:39:4510158 SSLSocketDataProvider ssl(ASYNC, OK);
10159 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10160
bncc958faa2015-07-31 18:14:5210161 TestCompletionCallback callback;
10162
danakj1fd259a02016-04-16 03:17:0910163 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10164 std::unique_ptr<HttpTransaction> trans(
bncc958faa2015-07-31 18:14:5210165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10166
10167 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110168 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
bncc958faa2015-07-31 18:14:5210169
bncb26024382016-06-29 02:39:4510170 url::SchemeHostPort test_server("https", "www.example.org", 443);
bnc525e175a2016-06-20 12:36:4010171 HttpServerProperties* http_server_properties =
10172 session->http_server_properties();
bncc958faa2015-07-31 18:14:5210173 AlternativeServiceVector alternative_service_vector =
bnc525e175a2016-06-20 12:36:4010174 http_server_properties->GetAlternativeServices(test_server);
bncc958faa2015-07-31 18:14:5210175 EXPECT_TRUE(alternative_service_vector.empty());
10176
robpercival214763f2016-07-01 23:27:0110177 EXPECT_THAT(callback.WaitForResult(), IsOk());
bncc958faa2015-07-31 18:14:5210178
10179 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210180 ASSERT_TRUE(response);
10181 ASSERT_TRUE(response->headers);
bncc958faa2015-07-31 18:14:5210182 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10183 EXPECT_FALSE(response->was_fetched_via_spdy);
10184 EXPECT_FALSE(response->was_npn_negotiated);
10185
10186 std::string response_data;
robpercival214763f2016-07-01 23:27:0110187 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
bncc958faa2015-07-31 18:14:5210188 EXPECT_EQ("hello world", response_data);
10189
10190 alternative_service_vector =
bnc525e175a2016-06-20 12:36:4010191 http_server_properties->GetAlternativeServices(test_server);
bncc958faa2015-07-31 18:14:5210192 ASSERT_EQ(2u, alternative_service_vector.size());
bnca9b9e222016-07-11 20:10:4010193 EXPECT_EQ(AlternateProtocolFromNextProto(kProtoHTTP2),
bncc958faa2015-07-31 18:14:5210194 alternative_service_vector[0].protocol);
10195 EXPECT_EQ("www.example.com", alternative_service_vector[0].host);
10196 EXPECT_EQ(443, alternative_service_vector[0].port);
bnca9b9e222016-07-11 20:10:4010197 EXPECT_EQ(AlternateProtocolFromNextProto(kProtoHTTP2),
bnc3f0118e2016-02-02 15:42:2210198 alternative_service_vector[1].protocol);
bncc958faa2015-07-31 18:14:5210199 EXPECT_EQ("www.example.org", alternative_service_vector[1].host);
10200 EXPECT_EQ(1234, alternative_service_vector[1].port);
10201}
10202
bncd16676a2016-07-20 16:23:0110203TEST_F(HttpNetworkTransactionTest, IdentifyQuicBroken) {
zhongyi3d4a55e72016-04-22 20:36:4610204 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0210205 HostPortPair alternative("alternative.example.org", 443);
10206 std::string origin_url = "https://origin.example.org:443";
10207 std::string alternative_url = "https://alternative.example.org:443";
10208
10209 // Negotiate HTTP/1.1 with alternative.example.org.
10210 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610211 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0210212 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10213
10214 // HTTP/1.1 data for request.
10215 MockWrite http_writes[] = {
10216 MockWrite("GET / HTTP/1.1\r\n"
10217 "Host: alternative.example.org\r\n"
10218 "Connection: keep-alive\r\n\r\n"),
10219 };
10220
10221 MockRead http_reads[] = {
10222 MockRead("HTTP/1.1 200 OK\r\n"
10223 "Content-Type: text/html; charset=iso-8859-1\r\n"
10224 "Content-Length: 40\r\n\r\n"
10225 "first HTTP/1.1 response from alternative"),
10226 };
10227 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10228 http_writes, arraysize(http_writes));
10229 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10230
10231 StaticSocketDataProvider data_refused;
10232 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10233 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10234
zhongyi3d4a55e72016-04-22 20:36:4610235 // Set up a QUIC alternative service for server.
danakj1fd259a02016-04-16 03:17:0910236 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4010237 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0210238 session->http_server_properties();
10239 AlternativeService alternative_service(QUIC, alternative);
10240 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyi3d4a55e72016-04-22 20:36:4610241 http_server_properties->SetAlternativeService(server, alternative_service,
rchdc7b9052016-03-17 20:51:5010242 expiration);
zhongyi48704c182015-12-07 07:52:0210243 // Mark the QUIC alternative service as broken.
10244 http_server_properties->MarkAlternativeServiceBroken(alternative_service);
10245
danakj1fd259a02016-04-16 03:17:0910246 std::unique_ptr<HttpTransaction> trans(
zhongyi48704c182015-12-07 07:52:0210247 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10248 HttpRequestInfo request;
10249 request.method = "GET";
10250 request.url = GURL(origin_url);
10251 request.load_flags = 0;
10252 TestCompletionCallback callback;
10253 NetErrorDetails details;
10254 EXPECT_FALSE(details.quic_broken);
10255
10256 trans->Start(&request, callback.callback(), BoundNetLog());
10257 trans->PopulateNetErrorDetails(&details);
10258 EXPECT_TRUE(details.quic_broken);
10259}
10260
bncd16676a2016-07-20 16:23:0110261TEST_F(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
zhongyi3d4a55e72016-04-22 20:36:4610262 url::SchemeHostPort server("https", "origin.example.org", 443);
zhongyi48704c182015-12-07 07:52:0210263 HostPortPair alternative1("alternative1.example.org", 443);
10264 HostPortPair alternative2("alternative2.example.org", 443);
10265 std::string origin_url = "https://origin.example.org:443";
10266 std::string alternative_url1 = "https://alternative1.example.org:443";
10267 std::string alternative_url2 = "https://alternative2.example.org:443";
10268
10269 // Negotiate HTTP/1.1 with alternative1.example.org.
10270 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610271 ssl.next_proto = kProtoHTTP11;
zhongyi48704c182015-12-07 07:52:0210272 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10273
10274 // HTTP/1.1 data for request.
10275 MockWrite http_writes[] = {
10276 MockWrite("GET / HTTP/1.1\r\n"
10277 "Host: alternative1.example.org\r\n"
10278 "Connection: keep-alive\r\n\r\n"),
10279 };
10280
10281 MockRead http_reads[] = {
10282 MockRead("HTTP/1.1 200 OK\r\n"
10283 "Content-Type: text/html; charset=iso-8859-1\r\n"
10284 "Content-Length: 40\r\n\r\n"
10285 "first HTTP/1.1 response from alternative1"),
10286 };
10287 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
10288 http_writes, arraysize(http_writes));
10289 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
10290
10291 StaticSocketDataProvider data_refused;
10292 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
10293 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
10294
danakj1fd259a02016-04-16 03:17:0910295 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4010296 HttpServerProperties* http_server_properties =
zhongyi48704c182015-12-07 07:52:0210297 session->http_server_properties();
10298
zhongyi3d4a55e72016-04-22 20:36:4610299 // Set up two QUIC alternative services for server.
zhongyi48704c182015-12-07 07:52:0210300 AlternativeServiceInfoVector alternative_service_info_vector;
10301 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
10302
10303 AlternativeService alternative_service1(QUIC, alternative1);
rchdc7b9052016-03-17 20:51:5010304 AlternativeServiceInfo alternative_service_info1(alternative_service1,
zhongyi48704c182015-12-07 07:52:0210305 expiration);
10306 alternative_service_info_vector.push_back(alternative_service_info1);
10307 AlternativeService alternative_service2(QUIC, alternative2);
rchdc7b9052016-03-17 20:51:5010308 AlternativeServiceInfo alternative_service_info2(alternative_service2,
zhongyi48704c182015-12-07 07:52:0210309 expiration);
10310 alternative_service_info_vector.push_back(alternative_service_info2);
10311
10312 http_server_properties->SetAlternativeServices(
zhongyi3d4a55e72016-04-22 20:36:4610313 server, alternative_service_info_vector);
zhongyi48704c182015-12-07 07:52:0210314
10315 // Mark one of the QUIC alternative service as broken.
10316 http_server_properties->MarkAlternativeServiceBroken(alternative_service1);
10317
10318 const AlternativeServiceVector alternative_service_vector =
zhongyi3d4a55e72016-04-22 20:36:4610319 http_server_properties->GetAlternativeServices(server);
zhongyi48704c182015-12-07 07:52:0210320
danakj1fd259a02016-04-16 03:17:0910321 std::unique_ptr<HttpTransaction> trans(
zhongyi48704c182015-12-07 07:52:0210322 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10323 HttpRequestInfo request;
10324 request.method = "GET";
10325 request.url = GURL(origin_url);
10326 request.load_flags = 0;
10327 TestCompletionCallback callback;
10328 NetErrorDetails details;
10329 EXPECT_FALSE(details.quic_broken);
10330
10331 trans->Start(&request, callback.callback(), BoundNetLog());
10332 trans->PopulateNetErrorDetails(&details);
10333 EXPECT_FALSE(details.quic_broken);
10334}
10335
bncd16676a2016-07-20 16:23:0110336TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]564b4912010-03-09 16:30:4210337 HttpRequestInfo request;
10338 request.method = "GET";
bncb26024382016-06-29 02:39:4510339 request.url = GURL("https://www.example.org/");
[email protected]564b4912010-03-09 16:30:4210340 request.load_flags = 0;
10341
[email protected]d973e99a2012-02-17 21:02:3610342 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:4210343 StaticSocketDataProvider first_data;
10344 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710345 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
bncb26024382016-06-29 02:39:4510346 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610347 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4510348 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]564b4912010-03-09 16:30:4210349
10350 MockRead data_reads[] = {
10351 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10352 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610353 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:4210354 };
10355 StaticSocketDataProvider second_data(
10356 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710357 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]564b4912010-03-09 16:30:4210358
danakj1fd259a02016-04-16 03:17:0910359 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]564b4912010-03-09 16:30:4210360
bnc525e175a2016-06-20 12:36:4010361 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5310362 session->http_server_properties();
zhongyi3d4a55e72016-04-22 20:36:4610363 const url::SchemeHostPort server(request.url);
[email protected]3912662a32011-10-04 00:51:1110364 // Port must be < 1024, or the header will be ignored (since initial port was
10365 // port 80 (another restricted port).
bncd9b132e2015-07-08 05:16:1010366 const AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010367 AlternateProtocolFromNextProto(kProtoHTTP2), "www.example.org",
bncd9b132e2015-07-08 05:16:1010368 666); // Port is ignored by MockConnect anyway.
bnc7dc7e1b42015-07-28 14:43:1210369 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyi3d4a55e72016-04-22 20:36:4610370 http_server_properties->SetAlternativeService(server, alternative_service,
10371 expiration);
[email protected]564b4912010-03-09 16:30:4210372
danakj1fd259a02016-04-16 03:17:0910373 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010374 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110375 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:4210376
[email protected]49639fa2011-12-20 23:22:4110377 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110378 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10379 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]564b4912010-03-09 16:30:4210380
10381 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210382 ASSERT_TRUE(response);
10383 ASSERT_TRUE(response->headers);
[email protected]564b4912010-03-09 16:30:4210384 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10385
10386 std::string response_data;
robpercival214763f2016-07-01 23:27:0110387 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]564b4912010-03-09 16:30:4210388 EXPECT_EQ("hello world", response_data);
10389
bncd9b132e2015-07-08 05:16:1010390 const AlternativeServiceVector alternative_service_vector =
zhongyi3d4a55e72016-04-22 20:36:4610391 http_server_properties->GetAlternativeServices(server);
bncd9b132e2015-07-08 05:16:1010392 ASSERT_EQ(1u, alternative_service_vector.size());
10393 EXPECT_EQ(alternative_service, alternative_service_vector[0]);
10394 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
10395 alternative_service_vector[0]));
[email protected]564b4912010-03-09 16:30:4210396}
10397
bnc55ff9da2015-08-19 18:42:3510398// Ensure that we are not allowed to redirect traffic via an alternate protocol
10399// to an unrestricted (port >= 1024) when the original traffic was on a
10400// restricted port (port < 1024). Ensure that we can redirect in all other
10401// cases.
bncd16676a2016-07-20 16:23:0110402TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
[email protected]3912662a32011-10-04 00:51:1110403 HttpRequestInfo restricted_port_request;
10404 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4510405 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110406 restricted_port_request.load_flags = 0;
10407
[email protected]d973e99a2012-02-17 21:02:3610408 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110409 StaticSocketDataProvider first_data;
10410 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710411 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110412
10413 MockRead data_reads[] = {
10414 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10415 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610416 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110417 };
10418 StaticSocketDataProvider second_data(
10419 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710420 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4510421 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610422 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4510423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1110424
danakj1fd259a02016-04-16 03:17:0910425 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110426
bnc525e175a2016-06-20 12:36:4010427 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5310428 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110429 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210430 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010431 AlternateProtocolFromNextProto(kProtoHTTP2), "www.example.org",
bnccacc0992015-03-20 20:22:2210432 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210433 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210434 http_server_properties->SetAlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4610435 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010436 expiration);
[email protected]3912662a32011-10-04 00:51:1110437
danakj1fd259a02016-04-16 03:17:0910438 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010439 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110440 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110441
[email protected]49639fa2011-12-20 23:22:4110442 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610443 &restricted_port_request,
10444 callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110445 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1110446 // Invalid change to unrestricted port should fail.
robpercival214763f2016-07-01 23:27:0110447 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
[email protected]c54c6962013-02-01 04:53:1910448}
[email protected]3912662a32011-10-04 00:51:1110449
bnc55ff9da2015-08-19 18:42:3510450// Ensure that we are allowed to redirect traffic via an alternate protocol to
10451// an unrestricted (port >= 1024) when the original traffic was on a restricted
10452// port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
bncd16676a2016-07-20 16:23:0110453TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
[email protected]bb88e1d32013-05-03 23:11:0710454 session_deps_.enable_user_alternate_protocol_ports = true;
[email protected]c54c6962013-02-01 04:53:1910455
10456 HttpRequestInfo restricted_port_request;
10457 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4510458 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]c54c6962013-02-01 04:53:1910459 restricted_port_request.load_flags = 0;
10460
10461 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
10462 StaticSocketDataProvider first_data;
10463 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710464 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]c54c6962013-02-01 04:53:1910465
10466 MockRead data_reads[] = {
10467 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10468 MockRead("hello world"),
10469 MockRead(ASYNC, OK),
10470 };
10471 StaticSocketDataProvider second_data(
10472 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710473 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4510474 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610475 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4510476 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]c54c6962013-02-01 04:53:1910477
danakj1fd259a02016-04-16 03:17:0910478 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]c54c6962013-02-01 04:53:1910479
bnc525e175a2016-06-20 12:36:4010480 HttpServerProperties* http_server_properties =
[email protected]c54c6962013-02-01 04:53:1910481 session->http_server_properties();
10482 const int kUnrestrictedAlternatePort = 1024;
bnccacc0992015-03-20 20:22:2210483 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010484 AlternateProtocolFromNextProto(kProtoHTTP2), "www.example.org",
bnccacc0992015-03-20 20:22:2210485 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210486 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210487 http_server_properties->SetAlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4610488 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010489 expiration);
[email protected]c54c6962013-02-01 04:53:1910490
danakj1fd259a02016-04-16 03:17:0910491 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010492 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]c54c6962013-02-01 04:53:1910493 TestCompletionCallback callback;
10494
10495 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
[email protected]262eec82013-03-19 21:01:3610496 &restricted_port_request,
10497 callback.callback(), BoundNetLog()));
[email protected]c54c6962013-02-01 04:53:1910498 // Change to unrestricted port should succeed.
robpercival214763f2016-07-01 23:27:0110499 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1110500}
10501
bnc55ff9da2015-08-19 18:42:3510502// Ensure that we are not allowed to redirect traffic via an alternate protocol
10503// to an unrestricted (port >= 1024) when the original traffic was on a
10504// restricted port (port < 1024). Ensure that we can redirect in all other
10505// cases.
bncd16676a2016-07-20 16:23:0110506TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
[email protected]3912662a32011-10-04 00:51:1110507 HttpRequestInfo restricted_port_request;
10508 restricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4510509 restricted_port_request.url = GURL("https://www.example.org:1023/");
[email protected]3912662a32011-10-04 00:51:1110510 restricted_port_request.load_flags = 0;
10511
[email protected]d973e99a2012-02-17 21:02:3610512 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110513 StaticSocketDataProvider first_data;
10514 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710515 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110516
10517 MockRead data_reads[] = {
10518 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10519 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610520 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110521 };
10522 StaticSocketDataProvider second_data(
10523 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710524 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110525
bncb26024382016-06-29 02:39:4510526 SSLSocketDataProvider ssl(ASYNC, OK);
10527 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10528
danakj1fd259a02016-04-16 03:17:0910529 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110530
bnc525e175a2016-06-20 12:36:4010531 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5310532 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110533 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210534 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010535 AlternateProtocolFromNextProto(kProtoHTTP2), "www.example.org",
bnccacc0992015-03-20 20:22:2210536 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210537 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210538 http_server_properties->SetAlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4610539 url::SchemeHostPort(restricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010540 expiration);
[email protected]3912662a32011-10-04 00:51:1110541
danakj1fd259a02016-04-16 03:17:0910542 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010543 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110544 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110545
[email protected]49639fa2011-12-20 23:22:4110546 int rv = trans->Start(
[email protected]262eec82013-03-19 21:01:3610547 &restricted_port_request,
10548 callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110549 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1110550 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0110551 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1110552}
10553
bnc55ff9da2015-08-19 18:42:3510554// Ensure that we are not allowed to redirect traffic via an alternate protocol
10555// to an unrestricted (port >= 1024) when the original traffic was on a
10556// restricted port (port < 1024). Ensure that we can redirect in all other
10557// cases.
bncd16676a2016-07-20 16:23:0110558TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
[email protected]3912662a32011-10-04 00:51:1110559 HttpRequestInfo unrestricted_port_request;
10560 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4510561 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110562 unrestricted_port_request.load_flags = 0;
10563
[email protected]d973e99a2012-02-17 21:02:3610564 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110565 StaticSocketDataProvider first_data;
10566 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710567 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110568
10569 MockRead data_reads[] = {
10570 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10571 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610572 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110573 };
10574 StaticSocketDataProvider second_data(
10575 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710576 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
bncb26024382016-06-29 02:39:4510577 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610578 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4510579 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]3912662a32011-10-04 00:51:1110580
danakj1fd259a02016-04-16 03:17:0910581 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110582
bnc525e175a2016-06-20 12:36:4010583 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5310584 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:1110585 const int kRestrictedAlternatePort = 80;
bnccacc0992015-03-20 20:22:2210586 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010587 AlternateProtocolFromNextProto(kProtoHTTP2), "www.example.org",
bnccacc0992015-03-20 20:22:2210588 kRestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210589 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210590 http_server_properties->SetAlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4610591 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010592 expiration);
[email protected]3912662a32011-10-04 00:51:1110593
danakj1fd259a02016-04-16 03:17:0910594 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010595 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110596 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110597
[email protected]49639fa2011-12-20 23:22:4110598 int rv = trans->Start(
10599 &unrestricted_port_request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110600 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1110601 // Valid change to restricted port should pass.
robpercival214763f2016-07-01 23:27:0110602 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1110603}
10604
bnc55ff9da2015-08-19 18:42:3510605// Ensure that we are not allowed to redirect traffic via an alternate protocol
10606// to an unrestricted (port >= 1024) when the original traffic was on a
10607// restricted port (port < 1024). Ensure that we can redirect in all other
10608// cases.
bncd16676a2016-07-20 16:23:0110609TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
[email protected]3912662a32011-10-04 00:51:1110610 HttpRequestInfo unrestricted_port_request;
10611 unrestricted_port_request.method = "GET";
bncb26024382016-06-29 02:39:4510612 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
[email protected]3912662a32011-10-04 00:51:1110613 unrestricted_port_request.load_flags = 0;
10614
[email protected]d973e99a2012-02-17 21:02:3610615 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:1110616 StaticSocketDataProvider first_data;
10617 first_data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0710618 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
[email protected]3912662a32011-10-04 00:51:1110619
10620 MockRead data_reads[] = {
10621 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10622 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610623 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:1110624 };
10625 StaticSocketDataProvider second_data(
10626 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710627 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
[email protected]3912662a32011-10-04 00:51:1110628
bncb26024382016-06-29 02:39:4510629 SSLSocketDataProvider ssl(ASYNC, OK);
10630 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10631
danakj1fd259a02016-04-16 03:17:0910632 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]3912662a32011-10-04 00:51:1110633
bnc525e175a2016-06-20 12:36:4010634 HttpServerProperties* http_server_properties =
[email protected]17291a022011-10-10 07:32:5310635 session->http_server_properties();
bnc0bbb02622015-07-23 10:06:2210636 const int kUnrestrictedAlternatePort = 1025;
bnccacc0992015-03-20 20:22:2210637 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010638 AlternateProtocolFromNextProto(kProtoHTTP2), "www.example.org",
bnccacc0992015-03-20 20:22:2210639 kUnrestrictedAlternatePort);
bnc7dc7e1b42015-07-28 14:43:1210640 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210641 http_server_properties->SetAlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4610642 url::SchemeHostPort(unrestricted_port_request.url), alternative_service,
rchdc7b9052016-03-17 20:51:5010643 expiration);
[email protected]3912662a32011-10-04 00:51:1110644
danakj1fd259a02016-04-16 03:17:0910645 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010646 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4110647 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:1110648
[email protected]49639fa2011-12-20 23:22:4110649 int rv = trans->Start(
10650 &unrestricted_port_request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110651 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]3912662a32011-10-04 00:51:1110652 // Valid change to an unrestricted port should pass.
robpercival214763f2016-07-01 23:27:0110653 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]3912662a32011-10-04 00:51:1110654}
10655
bnc55ff9da2015-08-19 18:42:3510656// Ensure that we are not allowed to redirect traffic via an alternate protocol
10657// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
10658// once the alternate protocol request fails.
bncd16676a2016-07-20 16:23:0110659TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
[email protected]eb6234e2012-01-19 01:50:0210660 HttpRequestInfo request;
10661 request.method = "GET";
bncce36dca22015-04-21 22:11:2310662 request.url = GURL("http://www.example.org/");
[email protected]eb6234e2012-01-19 01:50:0210663 request.load_flags = 0;
10664
10665 // The alternate protocol request will error out before we attempt to connect,
10666 // so only the standard HTTP request will try to connect.
10667 MockRead data_reads[] = {
10668 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
10669 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:0610670 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:0210671 };
10672 StaticSocketDataProvider data(
10673 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710674 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]eb6234e2012-01-19 01:50:0210675
danakj1fd259a02016-04-16 03:17:0910676 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]eb6234e2012-01-19 01:50:0210677
bnc525e175a2016-06-20 12:36:4010678 HttpServerProperties* http_server_properties =
[email protected]eb6234e2012-01-19 01:50:0210679 session->http_server_properties();
10680 const int kUnsafePort = 7;
bnccacc0992015-03-20 20:22:2210681 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4010682 AlternateProtocolFromNextProto(kProtoHTTP2), "www.example.org",
bnccacc0992015-03-20 20:22:2210683 kUnsafePort);
bnc7dc7e1b42015-07-28 14:43:1210684 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
bnccacc0992015-03-20 20:22:2210685 http_server_properties->SetAlternativeService(
zhongyi3d4a55e72016-04-22 20:36:4610686 url::SchemeHostPort(request.url), alternative_service, expiration);
[email protected]eb6234e2012-01-19 01:50:0210687
danakj1fd259a02016-04-16 03:17:0910688 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010689 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]eb6234e2012-01-19 01:50:0210690 TestCompletionCallback callback;
10691
10692 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]eb6234e2012-01-19 01:50:0210694 // The HTTP request should succeed.
robpercival214763f2016-07-01 23:27:0110695 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]eb6234e2012-01-19 01:50:0210696
[email protected]eb6234e2012-01-19 01:50:0210697 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210698 ASSERT_TRUE(response);
10699 ASSERT_TRUE(response->headers);
[email protected]eb6234e2012-01-19 01:50:0210700 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10701
10702 std::string response_data;
robpercival214763f2016-07-01 23:27:0110703 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]eb6234e2012-01-19 01:50:0210704 EXPECT_EQ("hello world", response_data);
10705}
10706
bncd16676a2016-07-20 16:23:0110707TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]2ff8b312010-04-26 22:20:5410708 HttpRequestInfo request;
10709 request.method = "GET";
bncb26024382016-06-29 02:39:4510710 request.url = GURL("https://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5410711 request.load_flags = 0;
10712
[email protected]2ff8b312010-04-26 22:20:5410713 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210714 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4310715 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5210716 MockRead("\r\n"),
10717 MockRead("hello world"),
10718 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10719 MockRead(ASYNC, OK)};
[email protected]2ff8b312010-04-26 22:20:5410720
10721 StaticSocketDataProvider first_transaction(
10722 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710723 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4510724 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610725 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4510726 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5410727
bncb26024382016-06-29 02:39:4510728 SSLSocketDataProvider ssl_http2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610729 ssl_http2.next_proto = kProtoHTTP2;
bncb26024382016-06-29 02:39:4510730 ssl_http2.cert =
10731 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10732 ASSERT_TRUE(ssl_http2.cert.get());
10733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http2);
[email protected]2ff8b312010-04-26 22:20:5410734
bncdf80d44fd2016-07-15 20:27:4110735 SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4510736 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4110737 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5410738
bnc42331402016-07-25 13:36:1510739 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4110740 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5410741 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110742 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5410743 };
10744
rch8e6c6c42015-05-01 14:05:1310745 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10746 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710747 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5410748
[email protected]d973e99a2012-02-17 21:02:3610749 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510750 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10751 NULL, 0, NULL, 0);
10752 hanging_non_alternate_protocol_socket.set_connect_data(
10753 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710754 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510755 &hanging_non_alternate_protocol_socket);
10756
[email protected]49639fa2011-12-20 23:22:4110757 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5410758
danakj1fd259a02016-04-16 03:17:0910759 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10760 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010761 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410762
[email protected]49639fa2011-12-20 23:22:4110763 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110764 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10765 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5410766
10767 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210768 ASSERT_TRUE(response);
10769 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5410770 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10771
10772 std::string response_data;
robpercival214763f2016-07-01 23:27:0110773 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5410774 EXPECT_EQ("hello world", response_data);
10775
[email protected]90499482013-06-01 00:39:5010776 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5410777
[email protected]49639fa2011-12-20 23:22:4110778 rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110779 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10780 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5410781
10782 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210783 ASSERT_TRUE(response);
10784 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0210785 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5310786 EXPECT_TRUE(response->was_fetched_via_spdy);
10787 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5410788
robpercival214763f2016-07-01 23:27:0110789 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5410790 EXPECT_EQ("hello!", response_data);
[email protected]2ff8b312010-04-26 22:20:5410791}
10792
bncd16676a2016-07-20 16:23:0110793TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
[email protected]2d6728692011-03-12 01:39:5510794 HttpRequestInfo request;
10795 request.method = "GET";
bncb26024382016-06-29 02:39:4510796 request.url = GURL("https://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510797 request.load_flags = 0;
10798
bncb26024382016-06-29 02:39:4510799 // First transaction receives Alt-Svc header over HTTP/1.1.
[email protected]2d6728692011-03-12 01:39:5510800 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210801 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4310802 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5210803 MockRead("\r\n"),
10804 MockRead("hello world"),
10805 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10806 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510807 };
10808
bncb26024382016-06-29 02:39:4510809 StaticSocketDataProvider http11_data(data_reads, arraysize(data_reads), NULL,
10810 0);
10811 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
[email protected]2d6728692011-03-12 01:39:5510812
bncb26024382016-06-29 02:39:4510813 SSLSocketDataProvider ssl_http11(ASYNC, OK);
10814 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
10815
10816 // Second transaction starts an alternative and a non-alternative Job.
10817 // Both sockets hang.
[email protected]d973e99a2012-02-17 21:02:3610818 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
mmenkecc2298e2015-12-07 18:20:1810819 StaticSocketDataProvider hanging_socket1(NULL, 0, NULL, 0);
10820 hanging_socket1.set_connect_data(never_finishing_connect);
mmenkecc2298e2015-12-07 18:20:1810821 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
10822
10823 StaticSocketDataProvider hanging_socket2(NULL, 0, NULL, 0);
10824 hanging_socket2.set_connect_data(never_finishing_connect);
10825 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
[email protected]2d6728692011-03-12 01:39:5510826
bncb26024382016-06-29 02:39:4510827 // Third transaction starts an alternative and a non-alternative job.
10828 // The non-alternative job hangs, but the alternative one succeeds.
10829 // The second transaction, still pending, binds to this socket.
bncdf80d44fd2016-07-15 20:27:4110830 SpdySerializedFrame req1(
bncb26024382016-06-29 02:39:4510831 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4110832 SpdySerializedFrame req2(
bncb26024382016-06-29 02:39:4510833 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
[email protected]2d6728692011-03-12 01:39:5510834 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4110835 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
[email protected]2d6728692011-03-12 01:39:5510836 };
bnc42331402016-07-25 13:36:1510837 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4110838 SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:1510839 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:4110840 SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]2d6728692011-03-12 01:39:5510841 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4110842 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
10843 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
rch8e6c6c42015-05-01 14:05:1310844 MockRead(ASYNC, 0, 6),
[email protected]2d6728692011-03-12 01:39:5510845 };
10846
rch8e6c6c42015-05-01 14:05:1310847 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
10848 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0710849 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2d6728692011-03-12 01:39:5510850
bncb26024382016-06-29 02:39:4510851 SSLSocketDataProvider ssl_http2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3610852 ssl_http2.next_proto = kProtoHTTP2;
bncb26024382016-06-29 02:39:4510853 ssl_http2.cert =
10854 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10855 ASSERT_TRUE(ssl_http2.cert);
10856 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http2);
10857
mmenkecc2298e2015-12-07 18:20:1810858 StaticSocketDataProvider hanging_socket3(NULL, 0, NULL, 0);
10859 hanging_socket3.set_connect_data(never_finishing_connect);
10860 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
[email protected]2d6728692011-03-12 01:39:5510861
danakj1fd259a02016-04-16 03:17:0910862 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]49639fa2011-12-20 23:22:4110863 TestCompletionCallback callback1;
[email protected]90499482013-06-01 00:39:5010864 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]2d6728692011-03-12 01:39:5510865
[email protected]49639fa2011-12-20 23:22:4110866 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110867 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10868 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5510869
10870 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5210871 ASSERT_TRUE(response);
10872 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5510873 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10874
10875 std::string response_data;
robpercival214763f2016-07-01 23:27:0110876 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5510877 EXPECT_EQ("hello world", response_data);
10878
[email protected]49639fa2011-12-20 23:22:4110879 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:5010880 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110881 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110882 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5510883
[email protected]49639fa2011-12-20 23:22:4110884 TestCompletionCallback callback3;
[email protected]90499482013-06-01 00:39:5010885 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
[email protected]49639fa2011-12-20 23:22:4110886 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110887 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]2d6728692011-03-12 01:39:5510888
robpercival214763f2016-07-01 23:27:0110889 EXPECT_THAT(callback2.WaitForResult(), IsOk());
10890 EXPECT_THAT(callback3.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5510891
10892 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5210893 ASSERT_TRUE(response);
10894 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0210895 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510896 EXPECT_TRUE(response->was_fetched_via_spdy);
10897 EXPECT_TRUE(response->was_npn_negotiated);
robpercival214763f2016-07-01 23:27:0110898 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5510899 EXPECT_EQ("hello!", response_data);
10900
10901 response = trans3.GetResponseInfo();
wezca1070932016-05-26 20:30:5210902 ASSERT_TRUE(response);
10903 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0210904 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]2d6728692011-03-12 01:39:5510905 EXPECT_TRUE(response->was_fetched_via_spdy);
10906 EXPECT_TRUE(response->was_npn_negotiated);
robpercival214763f2016-07-01 23:27:0110907 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5510908 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:5510909}
10910
bncd16676a2016-07-20 16:23:0110911TEST_F(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
[email protected]2d6728692011-03-12 01:39:5510912 HttpRequestInfo request;
10913 request.method = "GET";
bncb26024382016-06-29 02:39:4510914 request.url = GURL("https://www.example.org/");
[email protected]2d6728692011-03-12 01:39:5510915 request.load_flags = 0;
10916
[email protected]2d6728692011-03-12 01:39:5510917 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5210918 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4310919 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5210920 MockRead("\r\n"),
10921 MockRead("hello world"),
10922 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10923 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:5510924 };
10925
10926 StaticSocketDataProvider first_transaction(
10927 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0710928 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
[email protected]2d6728692011-03-12 01:39:5510929
[email protected]8ddf8322012-02-23 18:08:0610930 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0710931 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510932
[email protected]d973e99a2012-02-17 21:02:3610933 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5510934 StaticSocketDataProvider hanging_alternate_protocol_socket(
10935 NULL, 0, NULL, 0);
10936 hanging_alternate_protocol_socket.set_connect_data(
10937 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0710938 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5510939 &hanging_alternate_protocol_socket);
10940
bncb26024382016-06-29 02:39:4510941 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
mmenkecc2298e2015-12-07 18:20:1810942 StaticSocketDataProvider second_transaction(data_reads, arraysize(data_reads),
10943 NULL, 0);
10944 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
bncb26024382016-06-29 02:39:4510945 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:5510946
[email protected]49639fa2011-12-20 23:22:4110947 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:5510948
danakj1fd259a02016-04-16 03:17:0910949 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10950 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5010951 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510952
[email protected]49639fa2011-12-20 23:22:4110953 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110954 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10955 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5510956
10957 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210958 ASSERT_TRUE(response);
10959 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5510960 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10961
10962 std::string response_data;
robpercival214763f2016-07-01 23:27:0110963 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5510964 EXPECT_EQ("hello world", response_data);
10965
[email protected]90499482013-06-01 00:39:5010966 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2d6728692011-03-12 01:39:5510967
[email protected]49639fa2011-12-20 23:22:4110968 rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0110969 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10970 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2d6728692011-03-12 01:39:5510971
10972 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5210973 ASSERT_TRUE(response);
10974 ASSERT_TRUE(response->headers);
[email protected]2d6728692011-03-12 01:39:5510975 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10976 EXPECT_FALSE(response->was_fetched_via_spdy);
10977 EXPECT_FALSE(response->was_npn_negotiated);
10978
robpercival214763f2016-07-01 23:27:0110979 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2d6728692011-03-12 01:39:5510980 EXPECT_EQ("hello world", response_data);
[email protected]2d6728692011-03-12 01:39:5510981}
10982
[email protected]631f1322010-04-30 17:59:1110983class CapturingProxyResolver : public ProxyResolver {
10984 public:
sammce90c9212015-05-27 23:43:3510985 CapturingProxyResolver() {}
dchengb03027d2014-10-21 12:00:2010986 ~CapturingProxyResolver() override {}
[email protected]631f1322010-04-30 17:59:1110987
dchengb03027d2014-10-21 12:00:2010988 int GetProxyForURL(const GURL& url,
10989 ProxyInfo* results,
10990 const CompletionCallback& callback,
eroman9c8f4242016-02-29 21:16:5410991 RequestHandle* request,
dchengb03027d2014-10-21 12:00:2010992 const BoundNetLog& net_log) override {
[email protected]fae7669f2010-08-02 21:49:4010993 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
10994 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:4210995 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:1110996 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:4210997 return OK;
[email protected]631f1322010-04-30 17:59:1110998 }
10999
eroman9c8f4242016-02-29 21:16:5411000 void CancelRequest(RequestHandle request) override { NOTREACHED(); }
11001
11002 LoadState GetLoadState(RequestHandle request) const override {
11003 NOTREACHED();
11004 return LOAD_STATE_IDLE;
11005 }
11006
[email protected]24476402010-07-20 20:55:1711007 const std::vector<GURL>& resolved() const { return resolved_; }
11008
11009 private:
[email protected]631f1322010-04-30 17:59:1111010 std::vector<GURL> resolved_;
11011
11012 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
11013};
11014
sammce64b2362015-04-29 03:50:2311015class CapturingProxyResolverFactory : public ProxyResolverFactory {
11016 public:
11017 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
11018 : ProxyResolverFactory(false), resolver_(resolver) {}
11019
11020 int CreateProxyResolver(
11021 const scoped_refptr<ProxyResolverScriptData>& pac_script,
danakj1fd259a02016-04-16 03:17:0911022 std::unique_ptr<ProxyResolver>* resolver,
sammce64b2362015-04-29 03:50:2311023 const net::CompletionCallback& callback,
danakj1fd259a02016-04-16 03:17:0911024 std::unique_ptr<Request>* request) override {
sammce64b2362015-04-29 03:50:2311025 resolver->reset(new ForwardingProxyResolver(resolver_));
11026 return OK;
11027 }
11028
11029 private:
11030 ProxyResolver* resolver_;
11031};
11032
bnc2e884782016-08-11 19:45:1911033// Test that proxy is resolved using the origin url,
11034// regardless of the alternative server.
11035TEST_F(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
11036 // Configure proxy to bypass www.example.org, which is the origin URL.
11037 ProxyConfig proxy_config;
11038 proxy_config.proxy_rules().ParseFromString("myproxy:70");
11039 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
11040 auto proxy_config_service =
11041 base::MakeUnique<ProxyConfigServiceFixed>(proxy_config);
11042
11043 CapturingProxyResolver capturing_proxy_resolver;
11044 auto proxy_resolver_factory = base::MakeUnique<CapturingProxyResolverFactory>(
11045 &capturing_proxy_resolver);
11046
11047 TestNetLog net_log;
11048
11049 session_deps_.proxy_service = base::MakeUnique<ProxyService>(
11050 std::move(proxy_config_service), std::move(proxy_resolver_factory),
11051 &net_log);
11052
11053 session_deps_.net_log = &net_log;
11054
11055 // Configure alternative service with a hostname that is not bypassed by the
11056 // proxy.
11057 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11058 HttpServerProperties* http_server_properties =
11059 session->http_server_properties();
11060 url::SchemeHostPort server("https", "www.example.org", 443);
11061 HostPortPair alternative("www.example.com", 443);
11062 AlternativeService alternative_service(
11063 AlternateProtocolFromNextProto(kProtoHTTP2), alternative);
11064 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
11065 http_server_properties->SetAlternativeService(server, alternative_service,
11066 expiration);
11067
11068 // Non-alternative job should hang.
11069 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
11070 StaticSocketDataProvider hanging_alternate_protocol_socket(nullptr, 0,
11071 nullptr, 0);
11072 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
11073 session_deps_.socket_factory->AddSocketDataProvider(
11074 &hanging_alternate_protocol_socket);
11075
11076 SSLSocketDataProvider ssl_http2(ASYNC, OK);
11077 ssl_http2.next_proto = kProtoHTTP2;
11078 ssl_http2.cert =
11079 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11080 ASSERT_TRUE(ssl_http2.cert);
11081 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http2);
11082
11083 HttpRequestInfo request;
11084 request.method = "GET";
11085 request.url = GURL("https://www.example.org/");
11086 request.load_flags = 0;
11087
11088 SpdySerializedFrame req(
11089 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
11090
11091 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
11092
11093 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
11094 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
11095 MockRead spdy_reads[] = {
11096 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
11097 };
11098
11099 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11100 arraysize(spdy_writes));
11101 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11102
11103 TestCompletionCallback callback;
11104
11105 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11106
11107 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
11108 EXPECT_THAT(callback.GetResult(rv), IsOk());
11109
11110 const HttpResponseInfo* response = trans.GetResponseInfo();
11111 ASSERT_TRUE(response);
11112 ASSERT_TRUE(response->headers);
11113 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
11114 EXPECT_TRUE(response->was_fetched_via_spdy);
11115 EXPECT_TRUE(response->was_npn_negotiated);
11116
11117 std::string response_data;
11118 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
11119 EXPECT_EQ("hello!", response_data);
11120
11121 // Origin host bypasses proxy, no resolution should have happened.
11122 ASSERT_TRUE(capturing_proxy_resolver.resolved().empty());
11123}
11124
bncd16676a2016-07-20 16:23:0111125TEST_F(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
[email protected]631f1322010-04-30 17:59:1111126 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:4211127 proxy_config.set_auto_detect(true);
11128 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:1111129
sammc5dd160c2015-04-02 02:43:1311130 CapturingProxyResolver capturing_proxy_resolver;
[email protected]bb88e1d32013-05-03 23:11:0711131 session_deps_.proxy_service.reset(new ProxyService(
danakj1fd259a02016-04-16 03:17:0911132 base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
11133 base::WrapUnique(
sammce64b2362015-04-29 03:50:2311134 new CapturingProxyResolverFactory(&capturing_proxy_resolver)),
[email protected]66761b952010-06-25 21:30:3811135 NULL));
vishal.b62985ca92015-04-17 08:45:5111136 TestNetLog net_log;
[email protected]bb88e1d32013-05-03 23:11:0711137 session_deps_.net_log = &net_log;
[email protected]631f1322010-04-30 17:59:1111138
11139 HttpRequestInfo request;
11140 request.method = "GET";
bncb26024382016-06-29 02:39:4511141 request.url = GURL("https://www.example.org/");
[email protected]631f1322010-04-30 17:59:1111142 request.load_flags = 0;
11143
[email protected]631f1322010-04-30 17:59:1111144 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211145 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4311146 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5211147 MockRead("\r\n"),
11148 MockRead("hello world"),
11149 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
11150 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:1111151 };
11152
11153 StaticSocketDataProvider first_transaction(
11154 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0711155 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4511156 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611157 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4511158 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]631f1322010-04-30 17:59:1111159
bncb26024382016-06-29 02:39:4511160 SSLSocketDataProvider ssl_http2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611161 ssl_http2.next_proto = kProtoHTTP2;
bncb26024382016-06-29 02:39:4511162 ssl_http2.cert =
11163 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11164 ASSERT_TRUE(ssl_http2.cert);
11165 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http2);
[email protected]631f1322010-04-30 17:59:1111166
bncdf80d44fd2016-07-15 20:27:4111167 SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4511168 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
[email protected]631f1322010-04-30 17:59:1111169 MockWrite spdy_writes[] = {
rch8e6c6c42015-05-01 14:05:1311170 MockWrite(ASYNC, 0,
bnc8bef8da22016-05-30 01:28:2511171 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11172 "Host: www.example.org:443\r\n"
rch8e6c6c42015-05-01 14:05:1311173 "Proxy-Connection: keep-alive\r\n\r\n"),
bncdf80d44fd2016-07-15 20:27:4111174 CreateMockWrite(req, 2),
[email protected]631f1322010-04-30 17:59:1111175 };
11176
[email protected]d911f1b2010-05-05 22:39:4211177 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
11178
bnc42331402016-07-25 13:36:1511179 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4111180 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]631f1322010-04-30 17:59:1111181 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111182 MockRead(ASYNC, 1, kCONNECTResponse), CreateMockRead(resp, 3),
11183 CreateMockRead(data, 4), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
[email protected]631f1322010-04-30 17:59:1111184 };
11185
rch8e6c6c42015-05-01 14:05:1311186 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11187 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711188 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]631f1322010-04-30 17:59:1111189
[email protected]d973e99a2012-02-17 21:02:3611190 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:5511191 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
11192 NULL, 0, NULL, 0);
11193 hanging_non_alternate_protocol_socket.set_connect_data(
11194 never_finishing_connect);
[email protected]bb88e1d32013-05-03 23:11:0711195 session_deps_.socket_factory->AddSocketDataProvider(
[email protected]2d6728692011-03-12 01:39:5511196 &hanging_non_alternate_protocol_socket);
11197
[email protected]49639fa2011-12-20 23:22:4111198 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:1111199
danakj1fd259a02016-04-16 03:17:0911200 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11201 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011202 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1111203
mmenkee2172e42016-07-15 03:14:3211204 // HTTP/0.9 should fail.
[email protected]49639fa2011-12-20 23:22:4111205 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
mmenkee2172e42016-07-15 03:14:3211206 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
[email protected]631f1322010-04-30 17:59:1111207
[email protected]90499482013-06-01 00:39:5011208 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]631f1322010-04-30 17:59:1111209
[email protected]49639fa2011-12-20 23:22:4111210 rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0111211 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11212 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]631f1322010-04-30 17:59:1111213
mmenkee2172e42016-07-15 03:14:3211214 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211215 ASSERT_TRUE(response);
11216 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0211217 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311218 EXPECT_TRUE(response->was_fetched_via_spdy);
11219 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:1111220
mmenkee2172e42016-07-15 03:14:3211221 std::string response_data;
robpercival214763f2016-07-01 23:27:0111222 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]631f1322010-04-30 17:59:1111223 EXPECT_EQ("hello!", response_data);
bncb26024382016-06-29 02:39:4511224 ASSERT_EQ(2u, capturing_proxy_resolver.resolved().size());
11225 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311226 capturing_proxy_resolver.resolved()[0].spec());
bncce36dca22015-04-21 22:11:2311227 EXPECT_EQ("https://www.example.org/",
sammc5dd160c2015-04-02 02:43:1311228 capturing_proxy_resolver.resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:1111229
[email protected]029c83b62013-01-24 05:28:2011230 LoadTimingInfo load_timing_info;
11231 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
11232 TestLoadTimingNotReusedWithPac(load_timing_info,
11233 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]631f1322010-04-30 17:59:1111234}
[email protected]631f1322010-04-30 17:59:1111235
bncd16676a2016-07-20 16:23:0111236TEST_F(HttpNetworkTransactionTest,
bnc1c196c6e2016-05-28 13:51:4811237 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
[email protected]2ff8b312010-04-26 22:20:5411238 HttpRequestInfo request;
11239 request.method = "GET";
bncb26024382016-06-29 02:39:4511240 request.url = GURL("https://www.example.org/");
[email protected]2ff8b312010-04-26 22:20:5411241 request.load_flags = 0;
11242
[email protected]2ff8b312010-04-26 22:20:5411243 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211244 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4311245 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5211246 MockRead("\r\n"),
11247 MockRead("hello world"),
11248 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:5411249 };
11250
11251 StaticSocketDataProvider first_transaction(
11252 data_reads, arraysize(data_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0711253 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
bncb26024382016-06-29 02:39:4511254 SSLSocketDataProvider ssl_http11(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611255 ssl_http11.next_proto = kProtoHTTP11;
bncb26024382016-06-29 02:39:4511256 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
[email protected]2ff8b312010-04-26 22:20:5411257
bncb26024382016-06-29 02:39:4511258 SSLSocketDataProvider ssl_http2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611259 ssl_http2.next_proto = kProtoHTTP2;
bncb26024382016-06-29 02:39:4511260 ssl_http2.cert =
11261 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11262 ASSERT_TRUE(ssl_http2.cert);
11263 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http2);
[email protected]2ff8b312010-04-26 22:20:5411264
bncdf80d44fd2016-07-15 20:27:4111265 SpdySerializedFrame req(
bncb26024382016-06-29 02:39:4511266 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4111267 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]2ff8b312010-04-26 22:20:5411268
bnc42331402016-07-25 13:36:1511269 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4111270 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:5411271 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4111272 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]2ff8b312010-04-26 22:20:5411273 };
11274
rch8e6c6c42015-05-01 14:05:1311275 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
11276 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0711277 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]2ff8b312010-04-26 22:20:5411278
[email protected]83039bb2011-12-09 18:43:5511279 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:5411280
danakj1fd259a02016-04-16 03:17:0911281 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]2ff8b312010-04-26 22:20:5411282
danakj1fd259a02016-04-16 03:17:0911283 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011284 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411285
[email protected]49639fa2011-12-20 23:22:4111286 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0111287 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11288 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5411289
11290 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211291 ASSERT_TRUE(response);
11292 ASSERT_TRUE(response->headers);
[email protected]2ff8b312010-04-26 22:20:5411293 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11294
11295 std::string response_data;
robpercival214763f2016-07-01 23:27:0111296 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5411297 EXPECT_EQ("hello world", response_data);
11298
11299 // Set up an initial SpdySession in the pool to reuse.
bnc8bef8da22016-05-30 01:28:2511300 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4011301 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5311302 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2711303 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4211304 CreateSecureSpdySession(session.get(), key, BoundNetLog());
[email protected]02b0c342010-09-25 21:09:3811305
[email protected]90499482013-06-01 00:39:5011306 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]2ff8b312010-04-26 22:20:5411307
[email protected]49639fa2011-12-20 23:22:4111308 rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0111309 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11310 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]2ff8b312010-04-26 22:20:5411311
11312 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211313 ASSERT_TRUE(response);
11314 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0211315 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:5311316 EXPECT_TRUE(response->was_fetched_via_spdy);
11317 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:5411318
robpercival214763f2016-07-01 23:27:0111319 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]2ff8b312010-04-26 22:20:5411320 EXPECT_EQ("hello!", response_data);
[email protected]564b4912010-03-09 16:30:4211321}
11322
[email protected]044de0642010-06-17 10:42:1511323// GenerateAuthToken is a mighty big test.
11324// It tests all permutation of GenerateAuthToken behavior:
11325// - Synchronous and Asynchronous completion.
11326// - OK or error on completion.
11327// - Direct connection, non-authenticating proxy, and authenticating proxy.
11328// - HTTP or HTTPS backend (to include proxy tunneling).
11329// - Non-authenticating and authenticating backend.
11330//
[email protected]fe3b7dc2012-02-03 19:52:0911331// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:1511332// problems generating an auth token for an authenticating proxy, we don't
11333// need to test all permutations of the backend server).
11334//
11335// The test proceeds by going over each of the configuration cases, and
11336// potentially running up to three rounds in each of the tests. The TestConfig
11337// specifies both the configuration for the test as well as the expectations
11338// for the results.
bncd16676a2016-07-20 16:23:0111339TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:5011340 static const char kServer[] = "http://www.example.com";
11341 static const char kSecureServer[] = "https://www.example.com";
11342 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:1511343 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
11344
11345 enum AuthTiming {
11346 AUTH_NONE,
11347 AUTH_SYNC,
11348 AUTH_ASYNC,
11349 };
11350
11351 const MockWrite kGet(
11352 "GET / HTTP/1.1\r\n"
11353 "Host: www.example.com\r\n"
11354 "Connection: keep-alive\r\n\r\n");
11355 const MockWrite kGetProxy(
11356 "GET http://www.example.com/ HTTP/1.1\r\n"
11357 "Host: www.example.com\r\n"
11358 "Proxy-Connection: keep-alive\r\n\r\n");
11359 const MockWrite kGetAuth(
11360 "GET / HTTP/1.1\r\n"
11361 "Host: www.example.com\r\n"
11362 "Connection: keep-alive\r\n"
11363 "Authorization: auth_token\r\n\r\n");
11364 const MockWrite kGetProxyAuth(
11365 "GET http://www.example.com/ HTTP/1.1\r\n"
11366 "Host: www.example.com\r\n"
11367 "Proxy-Connection: keep-alive\r\n"
11368 "Proxy-Authorization: auth_token\r\n\r\n");
11369 const MockWrite kGetAuthThroughProxy(
11370 "GET http://www.example.com/ HTTP/1.1\r\n"
11371 "Host: www.example.com\r\n"
11372 "Proxy-Connection: keep-alive\r\n"
11373 "Authorization: auth_token\r\n\r\n");
11374 const MockWrite kGetAuthWithProxyAuth(
11375 "GET http://www.example.com/ HTTP/1.1\r\n"
11376 "Host: www.example.com\r\n"
11377 "Proxy-Connection: keep-alive\r\n"
11378 "Proxy-Authorization: auth_token\r\n"
11379 "Authorization: auth_token\r\n\r\n");
11380 const MockWrite kConnect(
11381 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711382 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511383 "Proxy-Connection: keep-alive\r\n\r\n");
11384 const MockWrite kConnectProxyAuth(
11385 "CONNECT www.example.com:443 HTTP/1.1\r\n"
rsleevidb16bb02015-11-12 23:47:1711386 "Host: www.example.com:443\r\n"
[email protected]044de0642010-06-17 10:42:1511387 "Proxy-Connection: keep-alive\r\n"
11388 "Proxy-Authorization: auth_token\r\n\r\n");
11389
11390 const MockRead kSuccess(
11391 "HTTP/1.1 200 OK\r\n"
11392 "Content-Type: text/html; charset=iso-8859-1\r\n"
11393 "Content-Length: 3\r\n\r\n"
11394 "Yes");
11395 const MockRead kFailure(
11396 "Should not be called.");
11397 const MockRead kServerChallenge(
11398 "HTTP/1.1 401 Unauthorized\r\n"
11399 "WWW-Authenticate: Mock realm=server\r\n"
11400 "Content-Type: text/html; charset=iso-8859-1\r\n"
11401 "Content-Length: 14\r\n\r\n"
11402 "Unauthorized\r\n");
11403 const MockRead kProxyChallenge(
11404 "HTTP/1.1 407 Unauthorized\r\n"
11405 "Proxy-Authenticate: Mock realm=proxy\r\n"
11406 "Proxy-Connection: close\r\n"
11407 "Content-Type: text/html; charset=iso-8859-1\r\n"
11408 "Content-Length: 14\r\n\r\n"
11409 "Unauthorized\r\n");
11410 const MockRead kProxyConnected(
11411 "HTTP/1.1 200 Connection Established\r\n\r\n");
11412
11413 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
11414 // no constructors, but the C++ compiler on Windows warns about
11415 // unspecified data in compound literals. So, moved to using constructors,
11416 // and TestRound's created with the default constructor should not be used.
11417 struct TestRound {
11418 TestRound()
11419 : expected_rv(ERR_UNEXPECTED),
11420 extra_write(NULL),
11421 extra_read(NULL) {
11422 }
11423 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11424 int expected_rv_arg)
11425 : write(write_arg),
11426 read(read_arg),
11427 expected_rv(expected_rv_arg),
11428 extra_write(NULL),
11429 extra_read(NULL) {
11430 }
11431 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
11432 int expected_rv_arg, const MockWrite* extra_write_arg,
[email protected]f871ee152012-07-27 19:02:0111433 const MockRead* extra_read_arg)
[email protected]044de0642010-06-17 10:42:1511434 : write(write_arg),
11435 read(read_arg),
11436 expected_rv(expected_rv_arg),
11437 extra_write(extra_write_arg),
11438 extra_read(extra_read_arg) {
11439 }
11440 MockWrite write;
11441 MockRead read;
11442 int expected_rv;
11443 const MockWrite* extra_write;
11444 const MockRead* extra_read;
11445 };
11446
11447 static const int kNoSSL = 500;
11448
11449 struct TestConfig {
thestig9d3bb0c2015-01-24 00:49:5111450 const char* const proxy_url;
[email protected]044de0642010-06-17 10:42:1511451 AuthTiming proxy_auth_timing;
11452 int proxy_auth_rv;
thestig9d3bb0c2015-01-24 00:49:5111453 const char* const server_url;
[email protected]044de0642010-06-17 10:42:1511454 AuthTiming server_auth_timing;
11455 int server_auth_rv;
11456 int num_auth_rounds;
11457 int first_ssl_round;
11458 TestRound rounds[3];
11459 } test_configs[] = {
11460 // Non-authenticating HTTP server with a direct connection.
11461 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11462 { TestRound(kGet, kSuccess, OK)}},
11463 // Authenticating HTTP server with a direct connection.
11464 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11465 { TestRound(kGet, kServerChallenge, OK),
11466 TestRound(kGetAuth, kSuccess, OK)}},
11467 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11468 { TestRound(kGet, kServerChallenge, OK),
11469 TestRound(kGetAuth, kFailure, kAuthErr)}},
11470 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11471 { TestRound(kGet, kServerChallenge, OK),
11472 TestRound(kGetAuth, kSuccess, OK)}},
11473 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11474 { TestRound(kGet, kServerChallenge, OK),
11475 TestRound(kGetAuth, kFailure, kAuthErr)}},
11476 // Non-authenticating HTTP server through a non-authenticating proxy.
11477 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
11478 { TestRound(kGetProxy, kSuccess, OK)}},
11479 // Authenticating HTTP server through a non-authenticating proxy.
11480 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
11481 { TestRound(kGetProxy, kServerChallenge, OK),
11482 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11483 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
11484 { TestRound(kGetProxy, kServerChallenge, OK),
11485 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11486 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
11487 { TestRound(kGetProxy, kServerChallenge, OK),
11488 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
11489 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
11490 { TestRound(kGetProxy, kServerChallenge, OK),
11491 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
11492 // Non-authenticating HTTP server through an authenticating proxy.
11493 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11494 { TestRound(kGetProxy, kProxyChallenge, OK),
11495 TestRound(kGetProxyAuth, kSuccess, OK)}},
11496 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11497 { TestRound(kGetProxy, kProxyChallenge, OK),
11498 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11499 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
11500 { TestRound(kGetProxy, kProxyChallenge, OK),
11501 TestRound(kGetProxyAuth, kSuccess, OK)}},
11502 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
11503 { TestRound(kGetProxy, kProxyChallenge, OK),
11504 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
11505 // Authenticating HTTP server through an authenticating proxy.
11506 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11507 { TestRound(kGetProxy, kProxyChallenge, OK),
11508 TestRound(kGetProxyAuth, kServerChallenge, OK),
11509 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11510 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11511 { TestRound(kGetProxy, kProxyChallenge, OK),
11512 TestRound(kGetProxyAuth, kServerChallenge, OK),
11513 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11514 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
11515 { TestRound(kGetProxy, kProxyChallenge, OK),
11516 TestRound(kGetProxyAuth, kServerChallenge, OK),
11517 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11518 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
11519 { TestRound(kGetProxy, kProxyChallenge, OK),
11520 TestRound(kGetProxyAuth, kServerChallenge, OK),
11521 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11522 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11523 { TestRound(kGetProxy, kProxyChallenge, OK),
11524 TestRound(kGetProxyAuth, kServerChallenge, OK),
11525 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11526 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11527 { TestRound(kGetProxy, kProxyChallenge, OK),
11528 TestRound(kGetProxyAuth, kServerChallenge, OK),
11529 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11530 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
11531 { TestRound(kGetProxy, kProxyChallenge, OK),
11532 TestRound(kGetProxyAuth, kServerChallenge, OK),
11533 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
11534 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
11535 { TestRound(kGetProxy, kProxyChallenge, OK),
11536 TestRound(kGetProxyAuth, kServerChallenge, OK),
11537 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
11538 // Non-authenticating HTTPS server with a direct connection.
11539 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11540 { TestRound(kGet, kSuccess, OK)}},
11541 // Authenticating HTTPS server with a direct connection.
11542 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11543 { TestRound(kGet, kServerChallenge, OK),
11544 TestRound(kGetAuth, kSuccess, OK)}},
11545 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11546 { TestRound(kGet, kServerChallenge, OK),
11547 TestRound(kGetAuth, kFailure, kAuthErr)}},
11548 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11549 { TestRound(kGet, kServerChallenge, OK),
11550 TestRound(kGetAuth, kSuccess, OK)}},
11551 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11552 { TestRound(kGet, kServerChallenge, OK),
11553 TestRound(kGetAuth, kFailure, kAuthErr)}},
11554 // Non-authenticating HTTPS server with a non-authenticating proxy.
11555 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
11556 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
11557 // Authenticating HTTPS server through a non-authenticating proxy.
11558 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
11559 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11560 TestRound(kGetAuth, kSuccess, OK)}},
11561 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
11562 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11563 TestRound(kGetAuth, kFailure, kAuthErr)}},
11564 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
11565 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11566 TestRound(kGetAuth, kSuccess, OK)}},
11567 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
11568 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
11569 TestRound(kGetAuth, kFailure, kAuthErr)}},
11570 // Non-Authenticating HTTPS server through an authenticating proxy.
11571 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11572 { TestRound(kConnect, kProxyChallenge, OK),
11573 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11574 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11575 { TestRound(kConnect, kProxyChallenge, OK),
11576 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11577 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
11578 { TestRound(kConnect, kProxyChallenge, OK),
11579 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
11580 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
11581 { TestRound(kConnect, kProxyChallenge, OK),
11582 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
11583 // Authenticating HTTPS server through an authenticating proxy.
11584 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11585 { TestRound(kConnect, kProxyChallenge, OK),
11586 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11587 &kGet, &kServerChallenge),
11588 TestRound(kGetAuth, kSuccess, OK)}},
11589 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11590 { TestRound(kConnect, kProxyChallenge, OK),
11591 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11592 &kGet, &kServerChallenge),
11593 TestRound(kGetAuth, kFailure, kAuthErr)}},
11594 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
11595 { TestRound(kConnect, kProxyChallenge, OK),
11596 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11597 &kGet, &kServerChallenge),
11598 TestRound(kGetAuth, kSuccess, OK)}},
11599 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
11600 { TestRound(kConnect, kProxyChallenge, OK),
11601 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11602 &kGet, &kServerChallenge),
11603 TestRound(kGetAuth, kFailure, kAuthErr)}},
11604 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11605 { TestRound(kConnect, kProxyChallenge, OK),
11606 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11607 &kGet, &kServerChallenge),
11608 TestRound(kGetAuth, kSuccess, OK)}},
11609 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11610 { TestRound(kConnect, kProxyChallenge, OK),
11611 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11612 &kGet, &kServerChallenge),
11613 TestRound(kGetAuth, kFailure, kAuthErr)}},
11614 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
11615 { TestRound(kConnect, kProxyChallenge, OK),
11616 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11617 &kGet, &kServerChallenge),
11618 TestRound(kGetAuth, kSuccess, OK)}},
11619 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
11620 { TestRound(kConnect, kProxyChallenge, OK),
11621 TestRound(kConnectProxyAuth, kProxyConnected, OK,
11622 &kGet, &kServerChallenge),
11623 TestRound(kGetAuth, kFailure, kAuthErr)}},
11624 };
11625
viettrungluue4a8b882014-10-16 06:17:3811626 for (size_t i = 0; i < arraysize(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:0811627 HttpAuthHandlerMock::Factory* auth_factory(
11628 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711629 session_deps_.http_auth_handler_factory.reset(auth_factory);
asanka5ffd5d72016-03-23 16:20:4911630 SSLInfo empty_ssl_info;
[email protected]044de0642010-06-17 10:42:1511631 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:2611632
11633 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:1511634 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:0811635 for (int n = 0; n < 2; n++) {
11636 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11637 std::string auth_challenge = "Mock realm=proxy";
11638 GURL origin(test_config.proxy_url);
[email protected]df41d0d82014-03-13 00:43:2411639 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11640 auth_challenge.end());
[email protected]2d01c262011-08-11 23:07:0811641 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
asanka5ffd5d72016-03-23 16:20:4911642 empty_ssl_info, origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811643 auth_handler->SetGenerateExpectation(
11644 test_config.proxy_auth_timing == AUTH_ASYNC,
11645 test_config.proxy_auth_rv);
11646 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
11647 }
[email protected]044de0642010-06-17 10:42:1511648 }
11649 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:0011650 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:1511651 std::string auth_challenge = "Mock realm=server";
11652 GURL origin(test_config.server_url);
[email protected]df41d0d82014-03-13 00:43:2411653 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11654 auth_challenge.end());
[email protected]044de0642010-06-17 10:42:1511655 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
asanka5ffd5d72016-03-23 16:20:4911656 empty_ssl_info, origin, BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511657 auth_handler->SetGenerateExpectation(
11658 test_config.server_auth_timing == AUTH_ASYNC,
11659 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:0811660 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:1511661 }
11662 if (test_config.proxy_url) {
rdsmith82957ad2015-09-16 19:42:0311663 session_deps_.proxy_service =
11664 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:1511665 } else {
rdsmith82957ad2015-09-16 19:42:0311666 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:1511667 }
11668
11669 HttpRequestInfo request;
11670 request.method = "GET";
11671 request.url = GURL(test_config.server_url);
11672 request.load_flags = 0;
11673
danakj1fd259a02016-04-16 03:17:0911674 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]044de0642010-06-17 10:42:1511675
rchcb68dc62015-05-21 04:45:3611676 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
11677
11678 std::vector<std::vector<MockRead>> mock_reads(1);
11679 std::vector<std::vector<MockWrite>> mock_writes(1);
[email protected]044de0642010-06-17 10:42:1511680 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11681 const TestRound& read_write_round = test_config.rounds[round];
11682
11683 // Set up expected reads and writes.
rchcb68dc62015-05-21 04:45:3611684 mock_reads.back().push_back(read_write_round.read);
11685 mock_writes.back().push_back(read_write_round.write);
11686
11687 // kProxyChallenge uses Proxy-Connection: close which means that the
11688 // socket is closed and a new one will be created for the next request.
mmenkee71e15332015-10-07 16:39:5411689 if (read_write_round.read.data == kProxyChallenge.data) {
rchcb68dc62015-05-21 04:45:3611690 mock_reads.push_back(std::vector<MockRead>());
11691 mock_writes.push_back(std::vector<MockWrite>());
[email protected]044de0642010-06-17 10:42:1511692 }
11693
rchcb68dc62015-05-21 04:45:3611694 if (read_write_round.extra_read) {
11695 mock_reads.back().push_back(*read_write_round.extra_read);
[email protected]044de0642010-06-17 10:42:1511696 }
rchcb68dc62015-05-21 04:45:3611697 if (read_write_round.extra_write) {
11698 mock_writes.back().push_back(*read_write_round.extra_write);
11699 }
[email protected]044de0642010-06-17 10:42:1511700
11701 // Add an SSL sequence if necessary.
[email protected]044de0642010-06-17 10:42:1511702 if (round >= test_config.first_ssl_round)
[email protected]bb88e1d32013-05-03 23:11:0711703 session_deps_.socket_factory->AddSSLSocketDataProvider(
[email protected]044de0642010-06-17 10:42:1511704 &ssl_socket_data_provider);
rchcb68dc62015-05-21 04:45:3611705 }
[email protected]044de0642010-06-17 10:42:1511706
danakj1fd259a02016-04-16 03:17:0911707 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
rchcb68dc62015-05-21 04:45:3611708 for (size_t i = 0; i < mock_reads.size(); ++i) {
danakj1fd259a02016-04-16 03:17:0911709 data_providers.push_back(base::WrapUnique(new StaticSocketDataProvider(
davidben5f8b6bc2015-11-25 03:19:5411710 mock_reads[i].data(), mock_reads[i].size(), mock_writes[i].data(),
olli.raula525048c2015-12-10 07:38:3211711 mock_writes[i].size())));
rchcb68dc62015-05-21 04:45:3611712 session_deps_.socket_factory->AddSocketDataProvider(
olli.raula525048c2015-12-10 07:38:3211713 data_providers.back().get());
rchcb68dc62015-05-21 04:45:3611714 }
11715
mmenkecc2298e2015-12-07 18:20:1811716 // Transaction must be created after DataProviders, so it's destroyed before
11717 // they are as well.
11718 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11719
rchcb68dc62015-05-21 04:45:3611720 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
11721 const TestRound& read_write_round = test_config.rounds[round];
[email protected]044de0642010-06-17 10:42:1511722 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:4111723 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:1511724 int rv;
11725 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:4111726 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:1511727 } else {
[email protected]49639fa2011-12-20 23:22:4111728 rv = trans.RestartWithAuth(
11729 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:1511730 }
11731 if (rv == ERR_IO_PENDING)
11732 rv = callback.WaitForResult();
11733
11734 // Compare results with expected data.
11735 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:5011736 const HttpResponseInfo* response = trans.GetResponseInfo();
ttuttlec0c828492015-05-15 01:25:5511737 if (read_write_round.expected_rv != OK) {
[email protected]044de0642010-06-17 10:42:1511738 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
11739 continue;
11740 }
11741 if (round + 1 < test_config.num_auth_rounds) {
wezca1070932016-05-26 20:30:5211742 EXPECT_TRUE(response->auth_challenge);
[email protected]044de0642010-06-17 10:42:1511743 } else {
wezca1070932016-05-26 20:30:5211744 EXPECT_FALSE(response->auth_challenge);
[email protected]044de0642010-06-17 10:42:1511745 }
11746 }
[email protected]e5ae96a2010-04-14 20:12:4511747 }
11748}
11749
bncd16676a2016-07-20 16:23:0111750TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
[email protected]c871bce92010-07-15 21:51:1411751 // Do multi-round authentication and make sure it works correctly.
[email protected]c871bce92010-07-15 21:51:1411752 HttpAuthHandlerMock::Factory* auth_factory(
11753 new HttpAuthHandlerMock::Factory());
[email protected]bb88e1d32013-05-03 23:11:0711754 session_deps_.http_auth_handler_factory.reset(auth_factory);
rdsmith82957ad2015-09-16 19:42:0311755 session_deps_.proxy_service = ProxyService::CreateDirect();
[email protected]bb88e1d32013-05-03 23:11:0711756 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
11757 session_deps_.host_resolver->set_synchronous_mode(true);
[email protected]c871bce92010-07-15 21:51:1411758
11759 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
11760 auth_handler->set_connection_based(true);
11761 std::string auth_challenge = "Mock realm=server";
11762 GURL origin("http://www.example.com");
[email protected]df41d0d82014-03-13 00:43:2411763 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
11764 auth_challenge.end());
asanka5ffd5d72016-03-23 16:20:4911765 SSLInfo empty_ssl_info;
[email protected]c871bce92010-07-15 21:51:1411766 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
asanka5ffd5d72016-03-23 16:20:4911767 empty_ssl_info, origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:0811768 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:1411769
[email protected]c871bce92010-07-15 21:51:1411770 int rv = OK;
11771 const HttpResponseInfo* response = NULL;
11772 HttpRequestInfo request;
11773 request.method = "GET";
11774 request.url = origin;
11775 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:2711776
danakj1fd259a02016-04-16 03:17:0911777 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]7ef4cbbb2011-02-06 11:19:1011778
11779 // Use a TCP Socket Pool with only one connection per group. This is used
11780 // to validate that the TCP socket is not released to the pool between
11781 // each round of multi-round authentication.
mmenkee65e7af2015-10-13 17:16:4211782 HttpNetworkSessionPeer session_peer(session.get());
[email protected]ab739042011-04-07 15:22:2811783 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:1011784 50, // Max sockets for pool
11785 1, // Max sockets per group
tbansal7b403bcc2016-04-13 22:33:2111786 session_deps_.host_resolver.get(), session_deps_.socket_factory.get(),
11787 NULL, session_deps_.net_log);
danakj1fd259a02016-04-16 03:17:0911788 std::unique_ptr<MockClientSocketPoolManager> mock_pool_manager(
[email protected]831e4a32013-11-14 02:14:4411789 new MockClientSocketPoolManager);
[email protected]a42dbd142011-11-17 16:42:0211790 mock_pool_manager->SetTransportSocketPool(transport_pool);
dchengc7eeda422015-12-26 03:56:4811791 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
[email protected]7ef4cbbb2011-02-06 11:19:1011792
danakj1fd259a02016-04-16 03:17:0911793 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011794 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111795 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:1411796
11797 const MockWrite kGet(
11798 "GET / HTTP/1.1\r\n"
11799 "Host: www.example.com\r\n"
11800 "Connection: keep-alive\r\n\r\n");
11801 const MockWrite kGetAuth(
11802 "GET / HTTP/1.1\r\n"
11803 "Host: www.example.com\r\n"
11804 "Connection: keep-alive\r\n"
11805 "Authorization: auth_token\r\n\r\n");
11806
11807 const MockRead kServerChallenge(
11808 "HTTP/1.1 401 Unauthorized\r\n"
11809 "WWW-Authenticate: Mock realm=server\r\n"
11810 "Content-Type: text/html; charset=iso-8859-1\r\n"
11811 "Content-Length: 14\r\n\r\n"
11812 "Unauthorized\r\n");
11813 const MockRead kSuccess(
11814 "HTTP/1.1 200 OK\r\n"
11815 "Content-Type: text/html; charset=iso-8859-1\r\n"
11816 "Content-Length: 3\r\n\r\n"
11817 "Yes");
11818
11819 MockWrite writes[] = {
11820 // First round
11821 kGet,
11822 // Second round
11823 kGetAuth,
11824 // Third round
11825 kGetAuth,
[email protected]eca50e122010-09-11 14:03:3011826 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:1011827 kGetAuth,
11828 // Competing request
11829 kGet,
[email protected]c871bce92010-07-15 21:51:1411830 };
11831 MockRead reads[] = {
11832 // First round
11833 kServerChallenge,
11834 // Second round
11835 kServerChallenge,
11836 // Third round
[email protected]eca50e122010-09-11 14:03:3011837 kServerChallenge,
11838 // Fourth round
[email protected]c871bce92010-07-15 21:51:1411839 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:1011840 // Competing response
11841 kSuccess,
[email protected]c871bce92010-07-15 21:51:1411842 };
11843 StaticSocketDataProvider data_provider(reads, arraysize(reads),
11844 writes, arraysize(writes));
[email protected]bb88e1d32013-05-03 23:11:0711845 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
[email protected]c871bce92010-07-15 21:51:1411846
thestig9d3bb0c2015-01-24 00:49:5111847 const char kSocketGroup[] = "www.example.com:80";
[email protected]7ef4cbbb2011-02-06 11:19:1011848
11849 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:1411850 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111851 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:1411852 if (rv == ERR_IO_PENDING)
11853 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111854 EXPECT_THAT(rv, IsOk());
[email protected]c871bce92010-07-15 21:51:1411855 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211856 ASSERT_TRUE(response);
11857 EXPECT_TRUE(response->auth_challenge);
[email protected]ab739042011-04-07 15:22:2811858 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411859
[email protected]7ef4cbbb2011-02-06 11:19:1011860 // In between rounds, another request comes in for the same domain.
11861 // It should not be able to grab the TCP socket that trans has already
11862 // claimed.
danakj1fd259a02016-04-16 03:17:0911863 std::unique_ptr<HttpTransaction> trans_compete(
[email protected]90499482013-06-01 00:39:5011864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:4111865 TestCompletionCallback callback_compete;
11866 rv = trans_compete->Start(
11867 &request, callback_compete.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0111868 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]7ef4cbbb2011-02-06 11:19:1011869 // callback_compete.WaitForResult at this point would stall forever,
11870 // since the HttpNetworkTransaction does not release the request back to
11871 // the pool until after authentication completes.
11872
11873 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:1411874 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111875 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411876 if (rv == ERR_IO_PENDING)
11877 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111878 EXPECT_THAT(rv, IsOk());
[email protected]c871bce92010-07-15 21:51:1411879 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211880 ASSERT_TRUE(response);
11881 EXPECT_FALSE(response->auth_challenge);
[email protected]ab739042011-04-07 15:22:2811882 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411883
[email protected]7ef4cbbb2011-02-06 11:19:1011884 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:1411885 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111886 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:1411887 if (rv == ERR_IO_PENDING)
11888 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111889 EXPECT_THAT(rv, IsOk());
[email protected]c871bce92010-07-15 21:51:1411890 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211891 ASSERT_TRUE(response);
11892 EXPECT_FALSE(response->auth_challenge);
[email protected]ab739042011-04-07 15:22:2811893 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:3011894
[email protected]7ef4cbbb2011-02-06 11:19:1011895 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:3011896 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:4111897 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:3011898 if (rv == ERR_IO_PENDING)
11899 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0111900 EXPECT_THAT(rv, IsOk());
[email protected]eca50e122010-09-11 14:03:3011901 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211902 ASSERT_TRUE(response);
11903 EXPECT_FALSE(response->auth_challenge);
[email protected]ab739042011-04-07 15:22:2811904 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011905
11906 // Read the body since the fourth round was successful. This will also
11907 // release the socket back to the pool.
11908 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]90499482013-06-01 00:39:5011909 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011910 if (rv == ERR_IO_PENDING)
11911 rv = callback.WaitForResult();
11912 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011913 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011914 EXPECT_EQ(0, rv);
11915 // There are still 0 idle sockets, since the trans_compete transaction
11916 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:2811917 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:1011918
11919 // The competing request can now finish. Wait for the headers and then
11920 // read the body.
11921 rv = callback_compete.WaitForResult();
robpercival214763f2016-07-01 23:27:0111922 EXPECT_THAT(rv, IsOk());
[email protected]90499482013-06-01 00:39:5011923 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011924 if (rv == ERR_IO_PENDING)
11925 rv = callback.WaitForResult();
11926 EXPECT_EQ(3, rv);
[email protected]90499482013-06-01 00:39:5011927 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:1011928 EXPECT_EQ(0, rv);
11929
11930 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:2811931 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:1411932}
11933
[email protected]65041fa2010-05-21 06:56:5311934// This tests the case that a request is issued via http instead of spdy after
11935// npn is negotiated.
bncd16676a2016-07-20 16:23:0111936TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]65041fa2010-05-21 06:56:5311937 HttpRequestInfo request;
11938 request.method = "GET";
bncce36dca22015-04-21 22:11:2311939 request.url = GURL("https://www.example.org/");
[email protected]65041fa2010-05-21 06:56:5311940 request.load_flags = 0;
11941
11942 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2311943 MockWrite(
11944 "GET / HTTP/1.1\r\n"
11945 "Host: www.example.org\r\n"
11946 "Connection: keep-alive\r\n\r\n"),
[email protected]65041fa2010-05-21 06:56:5311947 };
11948
[email protected]65041fa2010-05-21 06:56:5311949 MockRead data_reads[] = {
bncc958faa2015-07-31 18:14:5211950 MockRead("HTTP/1.1 200 OK\r\n"),
bnc2df4b522016-07-08 18:17:4311951 MockRead(kAlternativeServiceHttpHeader),
bncc958faa2015-07-31 18:14:5211952 MockRead("\r\n"),
11953 MockRead("hello world"),
11954 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:5311955 };
11956
[email protected]8ddf8322012-02-23 18:08:0611957 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3611958 ssl.next_proto = kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:5311959
[email protected]bb88e1d32013-05-03 23:11:0711960 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:5311961
11962 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11963 data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0711964 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]65041fa2010-05-21 06:56:5311965
[email protected]49639fa2011-12-20 23:22:4111966 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:5311967
danakj1fd259a02016-04-16 03:17:0911968 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11969 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5011970 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]65041fa2010-05-21 06:56:5311971
[email protected]49639fa2011-12-20 23:22:4111972 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:5311973
robpercival214763f2016-07-01 23:27:0111974 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11975 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]65041fa2010-05-21 06:56:5311976
11977 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5211978 ASSERT_TRUE(response);
11979 ASSERT_TRUE(response->headers);
[email protected]65041fa2010-05-21 06:56:5311980 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11981
11982 std::string response_data;
robpercival214763f2016-07-01 23:27:0111983 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]65041fa2010-05-21 06:56:5311984 EXPECT_EQ("hello world", response_data);
11985
11986 EXPECT_FALSE(response->was_fetched_via_spdy);
11987 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]65041fa2010-05-21 06:56:5311988}
[email protected]26ef6582010-06-24 02:30:4711989
bnc55ff9da2015-08-19 18:42:3511990// Simulate the SSL handshake completing with an NPN negotiation followed by an
11991// immediate server closing of the socket.
11992// Regression test for https://crbug.com/46369.
bncd16676a2016-07-20 16:23:0111993TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
[email protected]26ef6582010-06-24 02:30:4711994 HttpRequestInfo request;
11995 request.method = "GET";
bncce36dca22015-04-21 22:11:2311996 request.url = GURL("https://www.example.org/");
[email protected]26ef6582010-06-24 02:30:4711997 request.load_flags = 0;
11998
[email protected]8ddf8322012-02-23 18:08:0611999 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612000 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0712001 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]26ef6582010-06-24 02:30:4712002
bncdf80d44fd2016-07-15 20:27:4112003 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4912004 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
bncdf80d44fd2016-07-15 20:27:4112005 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
[email protected]26ef6582010-06-24 02:30:4712006
12007 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0612008 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:4712009 };
12010
rch8e6c6c42015-05-01 14:05:1312011 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
12012 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712013 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]26ef6582010-06-24 02:30:4712014
[email protected]49639fa2011-12-20 23:22:4112015 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:4712016
danakj1fd259a02016-04-16 03:17:0912017 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12018 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012019 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]26ef6582010-06-24 02:30:4712020
[email protected]49639fa2011-12-20 23:22:4112021 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112022 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12023 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]26ef6582010-06-24 02:30:4712024}
[email protected]65d34382010-07-01 18:12:2612025
[email protected]795cbf82013-07-22 09:37:2712026// A subclass of HttpAuthHandlerMock that records the request URL when
12027// it gets it. This is needed since the auth handler may get destroyed
12028// before we get a chance to query it.
12029class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
12030 public:
12031 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
12032
dchengb03027d2014-10-21 12:00:2012033 ~UrlRecordingHttpAuthHandlerMock() override {}
[email protected]795cbf82013-07-22 09:37:2712034
12035 protected:
dchengb03027d2014-10-21 12:00:2012036 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
12037 const HttpRequestInfo* request,
12038 const CompletionCallback& callback,
12039 std::string* auth_token) override {
[email protected]795cbf82013-07-22 09:37:2712040 *url_ = request->url;
12041 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
12042 credentials, request, callback, auth_token);
12043 }
12044
12045 private:
12046 GURL* url_;
12047};
12048
[email protected]8e6441ca2010-08-19 05:56:3812049// Test that if we cancel the transaction as the connection is completing, that
12050// everything tears down correctly.
bncd16676a2016-07-20 16:23:0112051TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
[email protected]8e6441ca2010-08-19 05:56:3812052 // Setup everything about the connection to complete synchronously, so that
12053 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
12054 // for is the callback from the HttpStreamRequest.
12055 // Then cancel the transaction.
12056 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:3612057 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:3812058 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:0612059 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
12060 MockRead(SYNCHRONOUS, "hello world"),
12061 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:3812062 };
12063
[email protected]8e6441ca2010-08-19 05:56:3812064 HttpRequestInfo request;
12065 request.method = "GET";
bncce36dca22015-04-21 22:11:2312066 request.url = GURL("http://www.example.org/");
[email protected]8e6441ca2010-08-19 05:56:3812067 request.load_flags = 0;
12068
[email protected]bb88e1d32013-05-03 23:11:0712069 session_deps_.host_resolver->set_synchronous_mode(true);
danakj1fd259a02016-04-16 03:17:0912070 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12071 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4112072 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]cb9bf6ca2011-01-28 13:15:2712073
[email protected]8e6441ca2010-08-19 05:56:3812074 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12075 data.set_connect_data(mock_connect);
[email protected]bb88e1d32013-05-03 23:11:0712076 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]8e6441ca2010-08-19 05:56:3812077
[email protected]49639fa2011-12-20 23:22:4112078 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:3812079
vishal.b62985ca92015-04-17 08:45:5112080 BoundTestNetLog log;
[email protected]49639fa2011-12-20 23:22:4112081 int rv = trans->Start(&request, callback.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0112082 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8e6441ca2010-08-19 05:56:3812083 trans.reset(); // Cancel the transaction here.
12084
fdoray92e35a72016-06-10 15:54:5512085 base::RunLoop().RunUntilIdle();
[email protected]f45c1ee2010-08-03 00:54:3012086}
12087
[email protected]ecab6e052014-05-16 14:58:1212088// Test that if a transaction is cancelled after receiving the headers, the
12089// stream is drained properly and added back to the socket pool. The main
12090// purpose of this test is to make sure that an HttpStreamParser can be read
12091// from after the HttpNetworkTransaction and the objects it owns have been
12092// deleted.
12093// See http://crbug.com/368418
bncd16676a2016-07-20 16:23:0112094TEST_F(HttpNetworkTransactionTest, CancelAfterHeaders) {
[email protected]ecab6e052014-05-16 14:58:1212095 MockRead data_reads[] = {
12096 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
12097 MockRead(ASYNC, "Content-Length: 2\r\n"),
12098 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
12099 MockRead(ASYNC, "1"),
12100 // 2 async reads are necessary to trigger a ReadResponseBody call after the
12101 // HttpNetworkTransaction has been deleted.
12102 MockRead(ASYNC, "2"),
12103 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
12104 };
12105 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
12106 session_deps_.socket_factory->AddSocketDataProvider(&data);
12107
danakj1fd259a02016-04-16 03:17:0912108 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]ecab6e052014-05-16 14:58:1212109
12110 {
12111 HttpRequestInfo request;
12112 request.method = "GET";
bncce36dca22015-04-21 22:11:2312113 request.url = GURL("http://www.example.org/");
[email protected]ecab6e052014-05-16 14:58:1212114 request.load_flags = 0;
12115
dcheng48459ac22014-08-26 00:46:4112116 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
[email protected]ecab6e052014-05-16 14:58:1212117 TestCompletionCallback callback;
12118
12119 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112120 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]ecab6e052014-05-16 14:58:1212121 callback.WaitForResult();
12122
12123 const HttpResponseInfo* response = trans.GetResponseInfo();
wezca1070932016-05-26 20:30:5212124 ASSERT_TRUE(response);
12125 EXPECT_TRUE(response->headers);
[email protected]ecab6e052014-05-16 14:58:1212126 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12127
12128 // The transaction and HttpRequestInfo are deleted.
12129 }
12130
12131 // Let the HttpResponseBodyDrainer drain the socket.
fdoray92e35a72016-06-10 15:54:5512132 base::RunLoop().RunUntilIdle();
[email protected]ecab6e052014-05-16 14:58:1212133
12134 // Socket should now be idle, waiting to be reused.
dcheng48459ac22014-08-26 00:46:4112135 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]ecab6e052014-05-16 14:58:1212136}
12137
[email protected]76a505b2010-08-25 06:23:0012138// Test a basic GET request through a proxy.
bncd16676a2016-07-20 16:23:0112139TEST_F(HttpNetworkTransactionTest, ProxyGet) {
rdsmith82957ad2015-09-16 19:42:0312140 session_deps_.proxy_service =
12141 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112142 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712143 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0912144 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012145
[email protected]76a505b2010-08-25 06:23:0012146 HttpRequestInfo request;
12147 request.method = "GET";
bncce36dca22015-04-21 22:11:2312148 request.url = GURL("http://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012149
12150 MockWrite data_writes1[] = {
bncce36dca22015-04-21 22:11:2312151 MockWrite(
12152 "GET http://www.example.org/ HTTP/1.1\r\n"
12153 "Host: www.example.org\r\n"
12154 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012155 };
12156
12157 MockRead data_reads1[] = {
12158 MockRead("HTTP/1.1 200 OK\r\n"),
12159 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12160 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612161 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012162 };
12163
12164 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12165 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712166 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]76a505b2010-08-25 06:23:0012167
[email protected]49639fa2011-12-20 23:22:4112168 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012169
danakj1fd259a02016-04-16 03:17:0912170 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ryansturm49a8cb12016-06-15 16:51:0912172 BeforeHeadersSentHandler headers_handler;
12173 trans->SetBeforeHeadersSentCallback(
12174 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
12175 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5012176
[email protected]49639fa2011-12-20 23:22:4112177 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0112178 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0012179
12180 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112181 EXPECT_THAT(rv, IsOk());
[email protected]76a505b2010-08-25 06:23:0012182
12183 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212184 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0012185
12186 EXPECT_TRUE(response->headers->IsKeepAlive());
12187 EXPECT_EQ(200, response->headers->response_code());
12188 EXPECT_EQ(100, response->headers->GetContentLength());
12189 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512190 EXPECT_TRUE(
12191 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
ryansturm49a8cb12016-06-15 16:51:0912192 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
12193 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
12194 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]76a505b2010-08-25 06:23:0012195 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]029c83b62013-01-24 05:28:2012196
12197 LoadTimingInfo load_timing_info;
12198 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12199 TestLoadTimingNotReusedWithPac(load_timing_info,
12200 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
[email protected]76a505b2010-08-25 06:23:0012201}
12202
12203// Test a basic HTTPS GET request through a proxy.
bncd16676a2016-07-20 16:23:0112204TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
rdsmith82957ad2015-09-16 19:42:0312205 session_deps_.proxy_service =
12206 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112207 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712208 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0912209 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012210
[email protected]76a505b2010-08-25 06:23:0012211 HttpRequestInfo request;
12212 request.method = "GET";
bncce36dca22015-04-21 22:11:2312213 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012214
12215 // Since we have proxy, should try to establish tunnel.
12216 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712217 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12218 "Host: www.example.org:443\r\n"
12219 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012220
rsleevidb16bb02015-11-12 23:47:1712221 MockWrite("GET / HTTP/1.1\r\n"
12222 "Host: www.example.org\r\n"
12223 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012224 };
12225
12226 MockRead data_reads1[] = {
12227 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12228
12229 MockRead("HTTP/1.1 200 OK\r\n"),
12230 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12231 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612232 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:0012233 };
12234
12235 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12236 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712237 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612238 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712239 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012240
[email protected]49639fa2011-12-20 23:22:4112241 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012242
danakj1fd259a02016-04-16 03:17:0912243 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012244 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
ryansturm49a8cb12016-06-15 16:51:0912245 BeforeHeadersSentHandler headers_handler;
12246 trans->SetBeforeHeadersSentCallback(
12247 base::Bind(&BeforeHeadersSentHandler::OnBeforeHeadersSent,
12248 base::Unretained(&headers_handler)));
[email protected]0b0bf032010-09-21 18:08:5012249
[email protected]49639fa2011-12-20 23:22:4112250 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0112251 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0012252
12253 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112254 EXPECT_THAT(rv, IsOk());
mmenke43758e62015-05-04 21:09:4612255 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012256 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012257 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012258 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012259 NetLog::PHASE_NONE);
12260 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012261 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012262 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12263 NetLog::PHASE_NONE);
12264
12265 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212266 ASSERT_TRUE(response);
[email protected]76a505b2010-08-25 06:23:0012267
12268 EXPECT_TRUE(response->headers->IsKeepAlive());
12269 EXPECT_EQ(200, response->headers->response_code());
12270 EXPECT_EQ(100, response->headers->GetContentLength());
12271 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12272 EXPECT_TRUE(response->was_fetched_via_proxy);
[email protected]d8fc4722014-06-13 13:17:1512273 EXPECT_TRUE(
12274 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
ryansturm49a8cb12016-06-15 16:51:0912275 EXPECT_TRUE(headers_handler.observed_before_headers_sent());
12276 EXPECT_TRUE(headers_handler.observed_before_headers_sent_with_proxy());
12277 EXPECT_EQ("myproxy:70", headers_handler.observed_proxy_server_uri());
[email protected]029c83b62013-01-24 05:28:2012278
12279 LoadTimingInfo load_timing_info;
12280 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12281 TestLoadTimingNotReusedWithPac(load_timing_info,
12282 CONNECT_TIMING_HAS_SSL_TIMES);
[email protected]76a505b2010-08-25 06:23:0012283}
12284
rsleevidb16bb02015-11-12 23:47:1712285// Test a basic HTTPS GET request through a proxy, connecting to an IPv6
12286// literal host.
bncd16676a2016-07-20 16:23:0112287TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
rsleevidb16bb02015-11-12 23:47:1712288 session_deps_.proxy_service =
12289 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
12290 BoundTestNetLog log;
12291 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0912292 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
rsleevidb16bb02015-11-12 23:47:1712293
12294 HttpRequestInfo request;
12295 request.method = "GET";
12296 request.url = GURL("https://[::1]:443/");
12297
12298 // Since we have proxy, should try to establish tunnel.
12299 MockWrite data_writes1[] = {
12300 MockWrite("CONNECT [::1]:443 HTTP/1.1\r\n"
12301 "Host: [::1]:443\r\n"
12302 "Proxy-Connection: keep-alive\r\n\r\n"),
12303
12304 MockWrite("GET / HTTP/1.1\r\n"
12305 "Host: [::1]\r\n"
12306 "Connection: keep-alive\r\n\r\n"),
12307 };
12308
12309 MockRead data_reads1[] = {
12310 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
12311
12312 MockRead("HTTP/1.1 200 OK\r\n"),
12313 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12314 MockRead("Content-Length: 100\r\n\r\n"),
12315 MockRead(SYNCHRONOUS, OK),
12316 };
12317
12318 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12319 data_writes1, arraysize(data_writes1));
12320 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12321 SSLSocketDataProvider ssl(ASYNC, OK);
12322 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12323
12324 TestCompletionCallback callback1;
12325
danakj1fd259a02016-04-16 03:17:0912326 std::unique_ptr<HttpTransaction> trans(
rsleevidb16bb02015-11-12 23:47:1712327 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12328
12329 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0112330 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rsleevidb16bb02015-11-12 23:47:1712331
12332 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112333 EXPECT_THAT(rv, IsOk());
rsleevidb16bb02015-11-12 23:47:1712334 TestNetLogEntry::List entries;
12335 log.GetEntries(&entries);
12336 size_t pos = ExpectLogContainsSomewhere(
12337 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
12338 NetLog::PHASE_NONE);
12339 ExpectLogContainsSomewhere(
12340 entries, pos, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12341 NetLog::PHASE_NONE);
12342
12343 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5212344 ASSERT_TRUE(response);
rsleevidb16bb02015-11-12 23:47:1712345
12346 EXPECT_TRUE(response->headers->IsKeepAlive());
12347 EXPECT_EQ(200, response->headers->response_code());
12348 EXPECT_EQ(100, response->headers->GetContentLength());
12349 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
12350 EXPECT_TRUE(response->was_fetched_via_proxy);
12351 EXPECT_TRUE(
12352 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
12353
12354 LoadTimingInfo load_timing_info;
12355 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
12356 TestLoadTimingNotReusedWithPac(load_timing_info,
12357 CONNECT_TIMING_HAS_SSL_TIMES);
12358}
12359
[email protected]76a505b2010-08-25 06:23:0012360// Test a basic HTTPS GET request through a proxy, but the server hangs up
12361// while establishing the tunnel.
bncd16676a2016-07-20 16:23:0112362TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
rdsmith82957ad2015-09-16 19:42:0312363 session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
vishal.b62985ca92015-04-17 08:45:5112364 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712365 session_deps_.net_log = log.bound().net_log();
danakj1fd259a02016-04-16 03:17:0912366 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]76a505b2010-08-25 06:23:0012367
[email protected]76a505b2010-08-25 06:23:0012368 HttpRequestInfo request;
12369 request.method = "GET";
bncce36dca22015-04-21 22:11:2312370 request.url = GURL("https://www.example.org/");
[email protected]76a505b2010-08-25 06:23:0012371
12372 // Since we have proxy, should try to establish tunnel.
12373 MockWrite data_writes1[] = {
rsleevidb16bb02015-11-12 23:47:1712374 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12375 "Host: www.example.org:443\r\n"
12376 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012377
rsleevidb16bb02015-11-12 23:47:1712378 MockWrite("GET / HTTP/1.1\r\n"
12379 "Host: www.example.org\r\n"
12380 "Connection: keep-alive\r\n\r\n"),
[email protected]76a505b2010-08-25 06:23:0012381 };
12382
12383 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:0612384 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:0012385 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:0612386 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:0012387 };
12388
12389 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
12390 data_writes1, arraysize(data_writes1));
[email protected]bb88e1d32013-05-03 23:11:0712391 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:0612392 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bb88e1d32013-05-03 23:11:0712393 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]76a505b2010-08-25 06:23:0012394
[email protected]49639fa2011-12-20 23:22:4112395 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:0012396
danakj1fd259a02016-04-16 03:17:0912397 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012398 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]0b0bf032010-09-21 18:08:5012399
[email protected]49639fa2011-12-20 23:22:4112400 int rv = trans->Start(&request, callback1.callback(), log.bound());
robpercival214763f2016-07-01 23:27:0112401 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]76a505b2010-08-25 06:23:0012402
12403 rv = callback1.WaitForResult();
robpercival214763f2016-07-01 23:27:0112404 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
mmenke43758e62015-05-04 21:09:4612405 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:4012406 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:0012407 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012408 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:0012409 NetLog::PHASE_NONE);
12410 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:4012411 entries, pos,
[email protected]76a505b2010-08-25 06:23:0012412 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
12413 NetLog::PHASE_NONE);
12414}
12415
[email protected]749eefa82010-09-13 22:14:0312416// Test for crbug.com/55424.
bncd16676a2016-07-20 16:23:0112417TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
bncdf80d44fd2016-07-15 20:27:4112418 SpdySerializedFrame req(
bnc38dcd392016-02-09 23:19:4912419 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4112420 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
[email protected]749eefa82010-09-13 22:14:0312421
bnc42331402016-07-25 13:36:1512422 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4112423 SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]749eefa82010-09-13 22:14:0312424 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112425 CreateMockRead(resp, 1), CreateMockRead(data, 2), MockRead(ASYNC, 0, 3),
[email protected]749eefa82010-09-13 22:14:0312426 };
12427
rch8e6c6c42015-05-01 14:05:1312428 SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
12429 arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712430 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]749eefa82010-09-13 22:14:0312431
[email protected]8ddf8322012-02-23 18:08:0612432 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612433 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0712434 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]749eefa82010-09-13 22:14:0312435
danakj1fd259a02016-04-16 03:17:0912436 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]749eefa82010-09-13 22:14:0312437
12438 // Set up an initial SpdySession in the pool to reuse.
bncce36dca22015-04-21 22:11:2312439 HostPortPair host_port_pair("www.example.org", 443);
[email protected]e6d017652013-05-17 18:01:4012440 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:5312441 PRIVACY_MODE_DISABLED);
[email protected]795cbf82013-07-22 09:37:2712442 base::WeakPtr<SpdySession> spdy_session =
mmenkee65e7af2015-10-13 17:16:4212443 CreateInsecureSpdySession(session.get(), key, BoundNetLog());
[email protected]749eefa82010-09-13 22:14:0312444
12445 HttpRequestInfo request;
12446 request.method = "GET";
bncce36dca22015-04-21 22:11:2312447 request.url = GURL("https://www.example.org/");
[email protected]749eefa82010-09-13 22:14:0312448 request.load_flags = 0;
12449
12450 // This is the important line that marks this as a preconnect.
12451 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
12452
danakj1fd259a02016-04-16 03:17:0912453 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012454 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]749eefa82010-09-13 22:14:0312455
[email protected]41d64e82013-07-03 22:44:2612456 TestCompletionCallback callback;
[email protected]49639fa2011-12-20 23:22:4112457 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112458 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12459 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]749eefa82010-09-13 22:14:0312460}
12461
[email protected]73b8dd222010-11-11 19:55:2412462// Given a net error, cause that error to be returned from the first Write()
12463// call and verify that the HttpTransaction fails with that error.
[email protected]23e482282013-06-14 16:08:0212464void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
[email protected]bb88e1d32013-05-03 23:11:0712465 int error, IoMode mode) {
ttuttle859dc7a2015-04-23 19:42:2912466 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712467 request_info.url = GURL("https://www.example.com/");
12468 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912469 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712470
[email protected]8ddf8322012-02-23 18:08:0612471 SSLSocketDataProvider ssl_data(mode, OK);
ttuttle859dc7a2015-04-23 19:42:2912472 MockWrite data_writes[] = {
12473 MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:2412474 };
ttuttle859dc7a2015-04-23 19:42:2912475 StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes));
[email protected]bb88e1d32013-05-03 23:11:0712476 session_deps_.socket_factory->AddSocketDataProvider(&data);
12477 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
[email protected]73b8dd222010-11-11 19:55:2412478
danakj1fd259a02016-04-16 03:17:0912479 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12480 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012481 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]73b8dd222010-11-11 19:55:2412482
[email protected]49639fa2011-12-20 23:22:4112483 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912484 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
12485 if (rv == ERR_IO_PENDING)
[email protected]73b8dd222010-11-11 19:55:2412486 rv = callback.WaitForResult();
12487 ASSERT_EQ(error, rv);
12488}
12489
bncd16676a2016-07-20 16:23:0112490TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
[email protected]73b8dd222010-11-11 19:55:2412491 // Just check a grab bag of cert errors.
12492 static const int kErrors[] = {
12493 ERR_CERT_COMMON_NAME_INVALID,
12494 ERR_CERT_AUTHORITY_INVALID,
12495 ERR_CERT_DATE_INVALID,
12496 };
12497 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:0612498 CheckErrorIsPassedBack(kErrors[i], ASYNC);
12499 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:2412500 }
12501}
12502
[email protected]bd0b6772011-01-11 19:59:3012503// Ensure that a client certificate is removed from the SSL client auth
12504// cache when:
12505// 1) No proxy is involved.
12506// 2) TLS False Start is disabled.
12507// 3) The initial TLS handshake requests a client certificate.
12508// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0112509TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912510 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712511 request_info.url = GURL("https://www.example.com/");
12512 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912513 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712514
[email protected]bd0b6772011-01-11 19:59:3012515 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112516 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012517
12518 // [ssl_]data1 contains the data for the first SSL handshake. When a
12519 // CertificateRequest is received for the first time, the handshake will
12520 // be aborted to allow the caller to provide a certificate.
ttuttle859dc7a2015-04-23 19:42:2912521 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012522 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712523 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912524 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712525 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012526
12527 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
12528 // False Start is not being used, the result of the SSL handshake will be
12529 // returned as part of the SSLClientSocket::Connect() call. This test
12530 // matches the result of a server sending a handshake_failure alert,
12531 // rather than a Finished message, because it requires a client
12532 // certificate and none was supplied.
ttuttle859dc7a2015-04-23 19:42:2912533 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012534 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712535 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912536 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712537 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012538
12539 // [ssl_]data3 contains the data for the third SSL handshake. When a
12540 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212541 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
12542 // connection was attempted with TLSv1.2. This is transparent to the caller
[email protected]bd0b6772011-01-11 19:59:3012543 // of the HttpNetworkTransaction. Because this test failure is due to
12544 // requiring a client certificate, this fallback handshake should also
12545 // fail.
ttuttle859dc7a2015-04-23 19:42:2912546 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:3012547 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712548 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912549 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712550 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012551
[email protected]80c75f682012-05-26 16:22:1712552 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
12553 // connection to a server fails during an SSL handshake,
davidbenb937d6c2015-05-14 04:53:4212554 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
12555 // connection was attempted with TLSv1.1. This is transparent to the caller
[email protected]80c75f682012-05-26 16:22:1712556 // of the HttpNetworkTransaction. Because this test failure is due to
12557 // requiring a client certificate, this fallback handshake should also
12558 // fail.
ttuttle859dc7a2015-04-23 19:42:2912559 SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]80c75f682012-05-26 16:22:1712560 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712561 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912562 StaticSocketDataProvider data4(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712563 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712564
danakj1fd259a02016-04-16 03:17:0912565 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12566 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012567 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012568
[email protected]bd0b6772011-01-11 19:59:3012569 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:4112570 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912571 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112572 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3012573
12574 // Complete the SSL handshake, which should abort due to requiring a
12575 // client certificate.
12576 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112577 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3012578
12579 // Indicate that no certificate should be supplied. From the perspective
12580 // of SSLClientCertCache, NULL is just as meaningful as a real
12581 // certificate, so this is the same as supply a
12582 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412583 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
robpercival214763f2016-07-01 23:27:0112584 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3012585
12586 // Ensure the certificate was added to the client auth cache before
12587 // allowing the connection to continue restarting.
12588 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412589 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112590 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412591 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5212592 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3012593
12594 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712595 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12596 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012597 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112598 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3012599
12600 // Ensure that the client certificate is removed from the cache on a
12601 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112602 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412603 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012604}
12605
12606// Ensure that a client certificate is removed from the SSL client auth
12607// cache when:
12608// 1) No proxy is involved.
12609// 2) TLS False Start is enabled.
12610// 3) The initial TLS handshake requests a client certificate.
12611// 4) The client supplies an invalid/unacceptable certificate.
bncd16676a2016-07-20 16:23:0112612TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
ttuttle859dc7a2015-04-23 19:42:2912613 HttpRequestInfo request_info;
[email protected]cb9bf6ca2011-01-28 13:15:2712614 request_info.url = GURL("https://www.example.com/");
12615 request_info.method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912616 request_info.load_flags = LOAD_NORMAL;
[email protected]cb9bf6ca2011-01-28 13:15:2712617
[email protected]bd0b6772011-01-11 19:59:3012618 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112619 cert_request->host_and_port = HostPortPair("www.example.com", 443);
[email protected]bd0b6772011-01-11 19:59:3012620
12621 // When TLS False Start is used, SSLClientSocket::Connect() calls will
12622 // return successfully after reading up to the peer's Certificate message.
12623 // This is to allow the caller to call SSLClientSocket::Write(), which can
12624 // enqueue application data to be sent in the same packet as the
12625 // ChangeCipherSpec and Finished messages.
12626 // The actual handshake will be finished when SSLClientSocket::Read() is
12627 // called, which expects to process the peer's ChangeCipherSpec and
12628 // Finished messages. If there was an error negotiating with the peer,
12629 // such as due to the peer requiring a client certificate when none was
12630 // supplied, the alert sent by the peer won't be processed until Read() is
12631 // called.
12632
12633 // Like the non-False Start case, when a client certificate is requested by
12634 // the peer, the handshake is aborted during the Connect() call.
12635 // [ssl_]data1 represents the initial SSL handshake with the peer.
ttuttle859dc7a2015-04-23 19:42:2912636 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:3012637 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912639 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712640 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]bd0b6772011-01-11 19:59:3012641
12642 // When a client certificate is supplied, Connect() will not be aborted
12643 // when the peer requests the certificate. Instead, the handshake will
12644 // artificially succeed, allowing the caller to write the HTTP request to
12645 // the socket. The handshake messages are not processed until Read() is
12646 // called, which then detects that the handshake was aborted, due to the
12647 // peer sending a handshake_failure because it requires a client
12648 // certificate.
ttuttle859dc7a2015-04-23 19:42:2912649 SSLSocketDataProvider ssl_data2(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012650 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712651 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912652 MockRead data2_reads[] = {
12653 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:3012654 };
ttuttle859dc7a2015-04-23 19:42:2912655 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712656 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]bd0b6772011-01-11 19:59:3012657
12658 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
[email protected]80c75f682012-05-26 16:22:1712659 // the data for the SSL handshake once the TLSv1.1 connection falls back to
12660 // TLSv1. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912661 SSLSocketDataProvider ssl_data3(ASYNC, OK);
[email protected]bd0b6772011-01-11 19:59:3012662 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712663 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912664 StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712665 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]bd0b6772011-01-11 19:59:3012666
[email protected]80c75f682012-05-26 16:22:1712667 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
12668 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
ttuttle859dc7a2015-04-23 19:42:2912669 SSLSocketDataProvider ssl_data4(ASYNC, OK);
[email protected]80c75f682012-05-26 16:22:1712670 ssl_data4.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712671 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
ttuttle859dc7a2015-04-23 19:42:2912672 StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712673 session_deps_.socket_factory->AddSocketDataProvider(&data4);
[email protected]80c75f682012-05-26 16:22:1712674
[email protected]7799de12013-05-30 05:52:5112675 // Need one more if TLSv1.2 is enabled.
ttuttle859dc7a2015-04-23 19:42:2912676 SSLSocketDataProvider ssl_data5(ASYNC, OK);
[email protected]7799de12013-05-30 05:52:5112677 ssl_data5.cert_request_info = cert_request.get();
12678 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
ttuttle859dc7a2015-04-23 19:42:2912679 StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]7799de12013-05-30 05:52:5112680 session_deps_.socket_factory->AddSocketDataProvider(&data5);
12681
danakj1fd259a02016-04-16 03:17:0912682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12683 std::unique_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:5012684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]bd0b6772011-01-11 19:59:3012685
[email protected]bd0b6772011-01-11 19:59:3012686 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:4112687 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912688 int rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112689 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3012690
12691 // Complete the SSL handshake, which should abort due to requiring a
12692 // client certificate.
12693 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112694 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]bd0b6772011-01-11 19:59:3012695
12696 // Indicate that no certificate should be supplied. From the perspective
12697 // of SSLClientCertCache, NULL is just as meaningful as a real
12698 // certificate, so this is the same as supply a
12699 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412700 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
robpercival214763f2016-07-01 23:27:0112701 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]bd0b6772011-01-11 19:59:3012702
12703 // Ensure the certificate was added to the client auth cache before
12704 // allowing the connection to continue restarting.
12705 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412706 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112707 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412708 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5212709 ASSERT_FALSE(client_cert);
[email protected]bd0b6772011-01-11 19:59:3012710
[email protected]bd0b6772011-01-11 19:59:3012711 // Restart the handshake. This will consume ssl_data2, which fails, and
[email protected]80c75f682012-05-26 16:22:1712712 // then consume ssl_data3 and ssl_data4, both of which should also fail.
12713 // The result code is checked against what ssl_data4 should return.
[email protected]bd0b6772011-01-11 19:59:3012714 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112715 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
[email protected]bd0b6772011-01-11 19:59:3012716
12717 // Ensure that the client certificate is removed from the cache on a
12718 // handshake failure.
[email protected]791879c2013-12-17 07:22:4112719 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412720 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
[email protected]bd0b6772011-01-11 19:59:3012721}
12722
[email protected]8c405132011-01-11 22:03:1812723// Ensure that a client certificate is removed from the SSL client auth
12724// cache when:
12725// 1) An HTTPS proxy is involved.
12726// 3) The HTTPS proxy requests a client certificate.
12727// 4) The client supplies an invalid/unacceptable certificate for the
12728// proxy.
12729// The test is repeated twice, first for connecting to an HTTPS endpoint,
12730// then for connecting to an HTTP endpoint.
bncd16676a2016-07-20 16:23:0112731TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
rdsmith82957ad2015-09-16 19:42:0312732 session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70");
vishal.b62985ca92015-04-17 08:45:5112733 BoundTestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0712734 session_deps_.net_log = log.bound().net_log();
[email protected]8c405132011-01-11 22:03:1812735
12736 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
[email protected]791879c2013-12-17 07:22:4112737 cert_request->host_and_port = HostPortPair("proxy", 70);
[email protected]8c405132011-01-11 22:03:1812738
12739 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
12740 // [ssl_]data[1-3]. Rather than represending the endpoint
12741 // (www.example.com:443), they represent failures with the HTTPS proxy
12742 // (proxy:70).
ttuttle859dc7a2015-04-23 19:42:2912743 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:1812744 ssl_data1.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712745 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
ttuttle859dc7a2015-04-23 19:42:2912746 StaticSocketDataProvider data1(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712747 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8c405132011-01-11 22:03:1812748
ttuttle859dc7a2015-04-23 19:42:2912749 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812750 ssl_data2.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712751 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
ttuttle859dc7a2015-04-23 19:42:2912752 StaticSocketDataProvider data2(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712753 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8c405132011-01-11 22:03:1812754
[email protected]80c75f682012-05-26 16:22:1712755 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
12756#if 0
ttuttle859dc7a2015-04-23 19:42:2912757 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:1812758 ssl_data3.cert_request_info = cert_request.get();
[email protected]bb88e1d32013-05-03 23:11:0712759 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
ttuttle859dc7a2015-04-23 19:42:2912760 StaticSocketDataProvider data3(NULL, 0, NULL, 0);
[email protected]bb88e1d32013-05-03 23:11:0712761 session_deps_.socket_factory->AddSocketDataProvider(&data3);
[email protected]80c75f682012-05-26 16:22:1712762#endif
[email protected]8c405132011-01-11 22:03:1812763
ttuttle859dc7a2015-04-23 19:42:2912764 HttpRequestInfo requests[2];
[email protected]8c405132011-01-11 22:03:1812765 requests[0].url = GURL("https://www.example.com/");
12766 requests[0].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912767 requests[0].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812768
12769 requests[1].url = GURL("http://www.example.com/");
12770 requests[1].method = "GET";
ttuttle859dc7a2015-04-23 19:42:2912771 requests[1].load_flags = LOAD_NORMAL;
[email protected]8c405132011-01-11 22:03:1812772
12773 for (size_t i = 0; i < arraysize(requests); ++i) {
[email protected]bb88e1d32013-05-03 23:11:0712774 session_deps_.socket_factory->ResetNextMockIndexes();
danakj1fd259a02016-04-16 03:17:0912775 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12776 std::unique_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5012777 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]8c405132011-01-11 22:03:1812778
12779 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:4112780 TestCompletionCallback callback;
ttuttle859dc7a2015-04-23 19:42:2912781 int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112782 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c405132011-01-11 22:03:1812783
12784 // Complete the SSL handshake, which should abort due to requiring a
12785 // client certificate.
12786 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112787 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
[email protected]8c405132011-01-11 22:03:1812788
12789 // Indicate that no certificate should be supplied. From the perspective
12790 // of SSLClientCertCache, NULL is just as meaningful as a real
12791 // certificate, so this is the same as supply a
12792 // legitimate-but-unacceptable certificate.
svaldez7872fd02015-11-19 21:10:5412793 rv = trans->RestartWithCertificate(NULL, NULL, callback.callback());
robpercival214763f2016-07-01 23:27:0112794 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]8c405132011-01-11 22:03:1812795
12796 // Ensure the certificate was added to the client auth cache before
12797 // allowing the connection to continue restarting.
12798 scoped_refptr<X509Certificate> client_cert;
svaldez7872fd02015-11-19 21:10:5412799 scoped_refptr<SSLPrivateKey> client_private_key;
[email protected]791879c2013-12-17 07:22:4112800 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412801 HostPortPair("proxy", 70), &client_cert, &client_private_key));
wezca1070932016-05-26 20:30:5212802 ASSERT_FALSE(client_cert);
[email protected]8c405132011-01-11 22:03:1812803 // Ensure the certificate was NOT cached for the endpoint. This only
12804 // applies to HTTPS requests, but is fine to check for HTTP requests.
[email protected]791879c2013-12-17 07:22:4112805 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412806 HostPortPair("www.example.com", 443), &client_cert,
12807 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812808
12809 // Restart the handshake. This will consume ssl_data2, which fails, and
12810 // then consume ssl_data3, which should also fail. The result code is
12811 // checked against what ssl_data3 should return.
12812 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112813 ASSERT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
[email protected]8c405132011-01-11 22:03:1812814
12815 // Now that the new handshake has failed, ensure that the client
12816 // certificate was removed from the client auth cache.
[email protected]791879c2013-12-17 07:22:4112817 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412818 HostPortPair("proxy", 70), &client_cert, &client_private_key));
[email protected]791879c2013-12-17 07:22:4112819 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
svaldez7872fd02015-11-19 21:10:5412820 HostPortPair("www.example.com", 443), &client_cert,
12821 &client_private_key));
[email protected]8c405132011-01-11 22:03:1812822 }
12823}
12824
bncd16676a2016-07-20 16:23:0112825TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
[email protected]e3ceb682011-06-28 23:55:4612826 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712827 session_deps_.host_resolver.reset(new MockCachingHostResolver());
danakj1fd259a02016-04-16 03:17:0912828 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2612829 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12830 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4612831
[email protected]8ddf8322012-02-23 18:08:0612832 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612833 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0712834 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4612835
bncdf80d44fd2016-07-15 20:27:4112836 SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4912837 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812838 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:4112839 SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4912840 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4612841 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4112842 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4612843 };
bnc42331402016-07-25 13:36:1512844 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4112845 SpdySerializedFrame host1_resp_body(
12846 spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:1512847 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:4112848 SpdySerializedFrame host2_resp_body(
12849 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4612850 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112851 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
12852 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1312853 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4612854 };
12855
eroman36d84e54432016-03-17 03:23:0212856 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0212857 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312858 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12859 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712860 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4612861
[email protected]aa22b242011-11-16 18:58:2912862 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4612863 HttpRequestInfo request1;
12864 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312865 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4612866 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012867 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612868
[email protected]49639fa2011-12-20 23:22:4112869 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112870 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12871 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4612872
12873 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5212874 ASSERT_TRUE(response);
12875 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212876 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612877
12878 std::string response_data;
robpercival214763f2016-07-01 23:27:0112879 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4612880 EXPECT_EQ("hello!", response_data);
12881
12882 // Preload www.gmail.com into HostCache.
12883 HostPortPair host_port("www.gmail.com", 443);
[email protected]5109c1952013-08-20 18:44:1012884 HostResolver::RequestInfo resolve_info(host_port);
[email protected]e3ceb682011-06-28 23:55:4612885 AddressList ignored;
maksim.sisov31452af2016-07-27 06:38:1012886 std::unique_ptr<HostResolver::Request> request;
12887 rv = session_deps_.host_resolver->Resolve(resolve_info, DEFAULT_PRIORITY,
12888 &ignored, callback.callback(),
12889 &request, BoundNetLog());
robpercival214763f2016-07-01 23:27:0112890 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6e78dfb2011-07-28 21:34:4712891 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0112892 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4612893
12894 HttpRequestInfo request2;
12895 request2.method = "GET";
12896 request2.url = GURL("https://www.gmail.com/");
12897 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012898 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4612899
[email protected]49639fa2011-12-20 23:22:4112900 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112901 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12902 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4612903
12904 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5212905 ASSERT_TRUE(response);
12906 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212907 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4612908 EXPECT_TRUE(response->was_fetched_via_spdy);
12909 EXPECT_TRUE(response->was_npn_negotiated);
robpercival214763f2016-07-01 23:27:0112910 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4612911 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4612912}
12913
bncd16676a2016-07-20 16:23:0112914TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
[email protected]d2b5f092012-06-08 23:55:0212915 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
[email protected]bb88e1d32013-05-03 23:11:0712916 session_deps_.host_resolver.reset(new MockCachingHostResolver());
danakj1fd259a02016-04-16 03:17:0912917 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]d2b5f092012-06-08 23:55:0212918 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
12919 pool_peer.DisableDomainAuthenticationVerification();
12920
12921 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3612922 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0712923 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]d2b5f092012-06-08 23:55:0212924
bncdf80d44fd2016-07-15 20:27:4112925 SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4912926 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3812927 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:4112928 SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4912929 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
[email protected]d2b5f092012-06-08 23:55:0212930 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4112931 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]d2b5f092012-06-08 23:55:0212932 };
bnc42331402016-07-25 13:36:1512933 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4112934 SpdySerializedFrame host1_resp_body(
12935 spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:1512936 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:4112937 SpdySerializedFrame host2_resp_body(
12938 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]d2b5f092012-06-08 23:55:0212939 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4112940 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
12941 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1312942 MockRead(ASYNC, 0, 6),
[email protected]d2b5f092012-06-08 23:55:0212943 };
12944
eroman36d84e54432016-03-17 03:23:0212945 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0212946 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1312947 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
12948 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0712949 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]d2b5f092012-06-08 23:55:0212950
12951 TestCompletionCallback callback;
12952 HttpRequestInfo request1;
12953 request1.method = "GET";
bncce36dca22015-04-21 22:11:2312954 request1.url = GURL("https://www.example.org/");
[email protected]d2b5f092012-06-08 23:55:0212955 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012956 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212957
12958 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112959 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12960 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0212961
12962 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5212963 ASSERT_TRUE(response);
12964 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212965 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212966
12967 std::string response_data;
robpercival214763f2016-07-01 23:27:0112968 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0212969 EXPECT_EQ("hello!", response_data);
12970
12971 HttpRequestInfo request2;
12972 request2.method = "GET";
12973 request2.url = GURL("https://www.gmail.com/");
12974 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5012975 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]d2b5f092012-06-08 23:55:0212976
12977 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0112978 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12979 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]d2b5f092012-06-08 23:55:0212980
12981 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5212982 ASSERT_TRUE(response);
12983 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0212984 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]d2b5f092012-06-08 23:55:0212985 EXPECT_TRUE(response->was_fetched_via_spdy);
12986 EXPECT_TRUE(response->was_npn_negotiated);
robpercival214763f2016-07-01 23:27:0112987 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]d2b5f092012-06-08 23:55:0212988 EXPECT_EQ("hello!", response_data);
[email protected]d2b5f092012-06-08 23:55:0212989}
12990
ttuttle859dc7a2015-04-23 19:42:2912991class OneTimeCachingHostResolver : public HostResolver {
[email protected]e3ceb682011-06-28 23:55:4612992 public:
12993 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
12994 : host_port_(host_port) {}
dchengb03027d2014-10-21 12:00:2012995 ~OneTimeCachingHostResolver() override {}
[email protected]e3ceb682011-06-28 23:55:4612996
12997 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
12998
12999 // HostResolver methods:
dchengb03027d2014-10-21 12:00:2013000 int Resolve(const RequestInfo& info,
13001 RequestPriority priority,
13002 AddressList* addresses,
13003 const CompletionCallback& callback,
maksim.sisov31452af2016-07-27 06:38:1013004 std::unique_ptr<Request>* out_req,
dchengb03027d2014-10-21 12:00:2013005 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4013006 return host_resolver_.Resolve(
[email protected]5109c1952013-08-20 18:44:1013007 info, priority, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:4013008 }
13009
dchengb03027d2014-10-21 12:00:2013010 int ResolveFromCache(const RequestInfo& info,
13011 AddressList* addresses,
13012 const BoundNetLog& net_log) override {
[email protected]95a214c2011-08-04 21:50:4013013 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
13014 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:0913015 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:4613016 return rv;
13017 }
13018
[email protected]46da33be2011-07-19 21:58:0413019 MockCachingHostResolver* GetMockHostResolver() {
13020 return &host_resolver_;
13021 }
13022
[email protected]e3ceb682011-06-28 23:55:4613023 private:
13024 MockCachingHostResolver host_resolver_;
13025 const HostPortPair host_port_;
13026};
13027
bncd16676a2016-07-20 16:23:0113028TEST_F(HttpNetworkTransactionTest,
mmenke5c642132015-06-02 16:05:1313029 UseIPConnectionPoolingWithHostCacheExpiration) {
[email protected]e3ceb682011-06-28 23:55:4613030 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
[email protected]e3ceb682011-06-28 23:55:4613031 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
[email protected]c6bf8152012-12-02 07:43:3413032 HttpNetworkSession::Params params =
[email protected]bb88e1d32013-05-03 23:11:0713033 SpdySessionDependencies::CreateSessionParams(&session_deps_);
[email protected]e3ceb682011-06-28 23:55:4613034 params.host_resolver = &host_resolver;
danakj1fd259a02016-04-16 03:17:0913035 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]b9ec6882011-07-01 07:40:2613036 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
13037 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:4613038
[email protected]8ddf8322012-02-23 18:08:0613039 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613040 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0713041 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
[email protected]e3ceb682011-06-28 23:55:4613042
bncdf80d44fd2016-07-15 20:27:4113043 SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4913044 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
rdsmithebb50aa2015-11-12 03:44:3813045 spdy_util_.UpdateWithStreamDestruction(1);
bncdf80d44fd2016-07-15 20:27:4113046 SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4913047 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST));
[email protected]e3ceb682011-06-28 23:55:4613048 MockWrite spdy_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113049 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3),
[email protected]e3ceb682011-06-28 23:55:4613050 };
bnc42331402016-07-25 13:36:1513051 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113052 SpdySerializedFrame host1_resp_body(
13053 spdy_util_.ConstructSpdyDataFrame(1, true));
bnc42331402016-07-25 13:36:1513054 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:4113055 SpdySerializedFrame host2_resp_body(
13056 spdy_util_.ConstructSpdyDataFrame(3, true));
[email protected]e3ceb682011-06-28 23:55:4613057 MockRead spdy_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113058 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
13059 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
rch8e6c6c42015-05-01 14:05:1313060 MockRead(ASYNC, 0, 6),
[email protected]e3ceb682011-06-28 23:55:4613061 };
13062
eroman36d84e54432016-03-17 03:23:0213063 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
[email protected]d2b5f092012-06-08 23:55:0213064 MockConnect connect(ASYNC, OK, peer_addr);
rch8e6c6c42015-05-01 14:05:1313065 SequencedSocketData spdy_data(connect, spdy_reads, arraysize(spdy_reads),
13066 spdy_writes, arraysize(spdy_writes));
[email protected]bb88e1d32013-05-03 23:11:0713067 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
[email protected]e3ceb682011-06-28 23:55:4613068
[email protected]aa22b242011-11-16 18:58:2913069 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:4613070 HttpRequestInfo request1;
13071 request1.method = "GET";
bncce36dca22015-04-21 22:11:2313072 request1.url = GURL("https://www.example.org/");
[email protected]e3ceb682011-06-28 23:55:4613073 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013074 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613075
[email protected]49639fa2011-12-20 23:22:4113076 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13078 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4613079
13080 const HttpResponseInfo* response = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213081 ASSERT_TRUE(response);
13082 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213083 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613084
13085 std::string response_data;
robpercival214763f2016-07-01 23:27:0113086 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4613087 EXPECT_EQ("hello!", response_data);
13088
13089 // Preload cache entries into HostCache.
[email protected]5109c1952013-08-20 18:44:1013090 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
[email protected]e3ceb682011-06-28 23:55:4613091 AddressList ignored;
maksim.sisov31452af2016-07-27 06:38:1013092 std::unique_ptr<HostResolver::Request> request;
13093 rv = host_resolver.Resolve(resolve_info, DEFAULT_PRIORITY, &ignored,
13094 callback.callback(), &request, BoundNetLog());
robpercival214763f2016-07-01 23:27:0113095 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]6e78dfb2011-07-28 21:34:4713096 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0113097 EXPECT_THAT(rv, IsOk());
[email protected]e3ceb682011-06-28 23:55:4613098
13099 HttpRequestInfo request2;
13100 request2.method = "GET";
13101 request2.url = GURL("https://www.gmail.com/");
13102 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013103 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
[email protected]e3ceb682011-06-28 23:55:4613104
[email protected]49639fa2011-12-20 23:22:4113105 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113106 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13107 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]e3ceb682011-06-28 23:55:4613108
13109 response = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213110 ASSERT_TRUE(response);
13111 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213112 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]e3ceb682011-06-28 23:55:4613113 EXPECT_TRUE(response->was_fetched_via_spdy);
13114 EXPECT_TRUE(response->was_npn_negotiated);
robpercival214763f2016-07-01 23:27:0113115 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
[email protected]e3ceb682011-06-28 23:55:4613116 EXPECT_EQ("hello!", response_data);
[email protected]e3ceb682011-06-28 23:55:4613117}
13118
bncd16676a2016-07-20 16:23:0113119TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
bncce36dca22015-04-21 22:11:2313120 const std::string https_url = "https://www.example.org:8080/";
13121 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413122
13123 // SPDY GET for HTTPS URL
bncdf80d44fd2016-07-15 20:27:4113124 SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4913125 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
[email protected]8450d722012-07-02 19:14:0413126
13127 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4113128 CreateMockWrite(req1, 0),
[email protected]8450d722012-07-02 19:14:0413129 };
13130
bnc42331402016-07-25 13:36:1513131 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113132 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
13133 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
mmenkee24011922015-12-17 22:12:5913134 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
[email protected]8450d722012-07-02 19:14:0413135
rch8e6c6c42015-05-01 14:05:1313136 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13137 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413138 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713139 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413140
13141 // HTTP GET for the HTTP URL
13142 MockWrite writes2[] = {
rch8e6c6c42015-05-01 14:05:1313143 MockWrite(ASYNC, 0,
lgarrona91df87f2014-12-05 00:51:3413144 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2313145 "Host: www.example.org:8080\r\n"
lgarrona91df87f2014-12-05 00:51:3413146 "Connection: keep-alive\r\n\r\n"),
[email protected]8450d722012-07-02 19:14:0413147 };
13148
13149 MockRead reads2[] = {
rch8e6c6c42015-05-01 14:05:1313150 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
13151 MockRead(ASYNC, 2, "hello"),
13152 MockRead(ASYNC, OK, 3),
[email protected]8450d722012-07-02 19:14:0413153 };
13154
rch8e6c6c42015-05-01 14:05:1313155 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13156 arraysize(writes2));
[email protected]8450d722012-07-02 19:14:0413157
[email protected]8450d722012-07-02 19:14:0413158 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613159 ssl.next_proto = kProtoHTTP2;
[email protected]bb88e1d32013-05-03 23:11:0713160 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13161 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13162 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]8450d722012-07-02 19:14:0413163
danakj1fd259a02016-04-16 03:17:0913164 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]8450d722012-07-02 19:14:0413165
13166 // Start the first transaction to set up the SpdySession
13167 HttpRequestInfo request1;
13168 request1.method = "GET";
13169 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413170 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013171 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413172 TestCompletionCallback callback1;
13173 EXPECT_EQ(ERR_IO_PENDING,
13174 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
fdoray92e35a72016-06-10 15:54:5513175 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413176
robpercival214763f2016-07-01 23:27:0113177 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0413178 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13179
13180 // Now, start the HTTP request
13181 HttpRequestInfo request2;
13182 request2.method = "GET";
13183 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413184 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013185 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413186 TestCompletionCallback callback2;
13187 EXPECT_EQ(ERR_IO_PENDING,
13188 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
fdoray92e35a72016-06-10 15:54:5513189 base::RunLoop().RunUntilIdle();
[email protected]8450d722012-07-02 19:14:0413190
robpercival214763f2016-07-01 23:27:0113191 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]8450d722012-07-02 19:14:0413192 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13193}
13194
bnc5452e2a2015-05-08 16:27:4213195// Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
13196// with the alternative server. That connection should not be used.
bncd16676a2016-07-20 16:23:0113197TEST_F(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
bnc8bef8da22016-05-30 01:28:2513198 url::SchemeHostPort server("https", "www.example.org", 443);
13199 HostPortPair alternative("www.example.org", 444);
bnc5452e2a2015-05-08 16:27:4213200
bnc8bef8da22016-05-30 01:28:2513201 // Negotiate HTTP/1.1 with alternative.
bnc5452e2a2015-05-08 16:27:4213202 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613203 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4213204 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13205
13206 // No data should be read from the alternative, because HTTP/1.1 is
13207 // negotiated.
13208 StaticSocketDataProvider data;
13209 session_deps_.socket_factory->AddSocketDataProvider(&data);
13210
13211 // This test documents that an alternate Job should not be used if HTTP/1.1 is
zhongyi3d4a55e72016-04-22 20:36:4613212 // negotiated. In order to test this, a failed connection to the server is
bnc5452e2a2015-05-08 16:27:4213213 // mocked. This way the request relies on the alternate Job.
13214 StaticSocketDataProvider data_refused;
13215 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13216 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13217
zhongyi3d4a55e72016-04-22 20:36:4613218 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0913219 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013220 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4213221 session->http_server_properties();
13222 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4013223 AlternateProtocolFromNextProto(kProtoHTTP2), alternative);
bnc7dc7e1b42015-07-28 14:43:1213224 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyi3d4a55e72016-04-22 20:36:4613225 http_server_properties->SetAlternativeService(server, alternative_service,
rchdc7b9052016-03-17 20:51:5013226 expiration);
bnc5452e2a2015-05-08 16:27:4213227
danakj1fd259a02016-04-16 03:17:0913228 std::unique_ptr<HttpTransaction> trans(
bnc5452e2a2015-05-08 16:27:4213229 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13230 HttpRequestInfo request;
13231 request.method = "GET";
bnc8bef8da22016-05-30 01:28:2513232 request.url = GURL("https://www.example.org:443");
bnc5452e2a2015-05-08 16:27:4213233 request.load_flags = 0;
13234 TestCompletionCallback callback;
13235
13236 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
13237 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
13238 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113239 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NPN_NEGOTIATION_FAILED));
bnc5452e2a2015-05-08 16:27:4213240}
13241
bnc40448a532015-05-11 19:13:1413242// A request to a server with an alternative service fires two Jobs: one to the
zhongyi3d4a55e72016-04-22 20:36:4613243// server, and an alternate one to the alternative server. If the former
bnc40448a532015-05-11 19:13:1413244// succeeds, the request should succeed, even if the latter fails because
13245// HTTP/1.1 is negotiated which is insufficient for alternative service.
bncd16676a2016-07-20 16:23:0113246TEST_F(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
bnc8bef8da22016-05-30 01:28:2513247 url::SchemeHostPort server("https", "www.example.org", 443);
13248 HostPortPair alternative("www.example.org", 444);
bnc40448a532015-05-11 19:13:1413249
13250 // Negotiate HTTP/1.1 with alternative.
13251 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613252 alternative_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1413253 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
13254
13255 // No data should be read from the alternative, because HTTP/1.1 is
13256 // negotiated.
13257 StaticSocketDataProvider data;
13258 session_deps_.socket_factory->AddSocketDataProvider(&data);
13259
zhongyi3d4a55e72016-04-22 20:36:4613260 // Negotiate HTTP/1.1 with server.
bnc40448a532015-05-11 19:13:1413261 SSLSocketDataProvider origin_ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613262 origin_ssl.next_proto = kProtoHTTP11;
bnc40448a532015-05-11 19:13:1413263 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
13264
13265 MockWrite http_writes[] = {
bnc8bef8da22016-05-30 01:28:2513266 MockWrite("GET / HTTP/1.1\r\n"
13267 "Host: www.example.org\r\n"
13268 "Connection: keep-alive\r\n\r\n"),
13269 MockWrite("GET /second HTTP/1.1\r\n"
13270 "Host: www.example.org\r\n"
13271 "Connection: keep-alive\r\n\r\n"),
bnc40448a532015-05-11 19:13:1413272 };
13273
13274 MockRead http_reads[] = {
13275 MockRead("HTTP/1.1 200 OK\r\n"),
13276 MockRead("Content-Type: text/html\r\n"),
13277 MockRead("Content-Length: 6\r\n\r\n"),
13278 MockRead("foobar"),
13279 MockRead("HTTP/1.1 200 OK\r\n"),
13280 MockRead("Content-Type: text/html\r\n"),
13281 MockRead("Content-Length: 7\r\n\r\n"),
13282 MockRead("another"),
13283 };
13284 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13285 http_writes, arraysize(http_writes));
13286 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13287
zhongyi3d4a55e72016-04-22 20:36:4613288 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0913289 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013290 HttpServerProperties* http_server_properties =
bnc40448a532015-05-11 19:13:1413291 session->http_server_properties();
13292 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4013293 AlternateProtocolFromNextProto(kProtoHTTP2), alternative);
bnc7dc7e1b42015-07-28 14:43:1213294 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyi3d4a55e72016-04-22 20:36:4613295 http_server_properties->SetAlternativeService(server, alternative_service,
rchdc7b9052016-03-17 20:51:5013296 expiration);
bnc40448a532015-05-11 19:13:1413297
13298 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
13299 HttpRequestInfo request1;
13300 request1.method = "GET";
bnc8bef8da22016-05-30 01:28:2513301 request1.url = GURL("https://www.example.org:443");
bnc40448a532015-05-11 19:13:1413302 request1.load_flags = 0;
13303 TestCompletionCallback callback1;
13304
13305 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
13306 rv = callback1.GetResult(rv);
robpercival214763f2016-07-01 23:27:0113307 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1413308
13309 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
wezca1070932016-05-26 20:30:5213310 ASSERT_TRUE(response1);
13311 ASSERT_TRUE(response1->headers);
bnc40448a532015-05-11 19:13:1413312 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13313
13314 std::string response_data1;
robpercival214763f2016-07-01 23:27:0113315 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
bnc40448a532015-05-11 19:13:1413316 EXPECT_EQ("foobar", response_data1);
13317
13318 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
13319 // for alternative service.
13320 EXPECT_TRUE(
13321 http_server_properties->IsAlternativeServiceBroken(alternative_service));
13322
zhongyi3d4a55e72016-04-22 20:36:4613323 // Since |alternative_service| is broken, a second transaction to server
bnc40448a532015-05-11 19:13:1413324 // should not start an alternate Job. It should pool to existing connection
zhongyi3d4a55e72016-04-22 20:36:4613325 // to server.
bnc40448a532015-05-11 19:13:1413326 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
13327 HttpRequestInfo request2;
13328 request2.method = "GET";
bnc8bef8da22016-05-30 01:28:2513329 request2.url = GURL("https://www.example.org:443/second");
bnc40448a532015-05-11 19:13:1413330 request2.load_flags = 0;
13331 TestCompletionCallback callback2;
13332
13333 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
13334 rv = callback2.GetResult(rv);
robpercival214763f2016-07-01 23:27:0113335 EXPECT_THAT(rv, IsOk());
bnc40448a532015-05-11 19:13:1413336
13337 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
wezca1070932016-05-26 20:30:5213338 ASSERT_TRUE(response2);
13339 ASSERT_TRUE(response2->headers);
bnc40448a532015-05-11 19:13:1413340 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
13341
13342 std::string response_data2;
robpercival214763f2016-07-01 23:27:0113343 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
bnc40448a532015-05-11 19:13:1413344 EXPECT_EQ("another", response_data2);
13345}
13346
bnc5452e2a2015-05-08 16:27:4213347// Alternative service requires HTTP/2 (or SPDY), but there is already a
13348// HTTP/1.1 socket open to the alternative server. That socket should not be
13349// used.
bncd16676a2016-07-20 16:23:0113350TEST_F(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
zhongyi3d4a55e72016-04-22 20:36:4613351 url::SchemeHostPort server("https", "origin.example.org", 443);
bnc5452e2a2015-05-08 16:27:4213352 HostPortPair alternative("alternative.example.org", 443);
13353 std::string origin_url = "https://origin.example.org:443";
13354 std::string alternative_url = "https://alternative.example.org:443";
13355
13356 // Negotiate HTTP/1.1 with alternative.example.org.
13357 SSLSocketDataProvider ssl(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613358 ssl.next_proto = kProtoHTTP11;
bnc5452e2a2015-05-08 16:27:4213359 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13360
13361 // HTTP/1.1 data for |request1| and |request2|.
13362 MockWrite http_writes[] = {
13363 MockWrite(
13364 "GET / HTTP/1.1\r\n"
13365 "Host: alternative.example.org\r\n"
13366 "Connection: keep-alive\r\n\r\n"),
13367 MockWrite(
13368 "GET / HTTP/1.1\r\n"
13369 "Host: alternative.example.org\r\n"
13370 "Connection: keep-alive\r\n\r\n"),
13371 };
13372
13373 MockRead http_reads[] = {
13374 MockRead(
13375 "HTTP/1.1 200 OK\r\n"
13376 "Content-Type: text/html; charset=iso-8859-1\r\n"
13377 "Content-Length: 40\r\n\r\n"
13378 "first HTTP/1.1 response from alternative"),
13379 MockRead(
13380 "HTTP/1.1 200 OK\r\n"
13381 "Content-Type: text/html; charset=iso-8859-1\r\n"
13382 "Content-Length: 41\r\n\r\n"
13383 "second HTTP/1.1 response from alternative"),
13384 };
13385 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
13386 http_writes, arraysize(http_writes));
13387 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13388
13389 // This test documents that an alternate Job should not pool to an already
13390 // existing HTTP/1.1 connection. In order to test this, a failed connection
zhongyi3d4a55e72016-04-22 20:36:4613391 // to the server is mocked. This way |request2| relies on the alternate Job.
bnc5452e2a2015-05-08 16:27:4213392 StaticSocketDataProvider data_refused;
13393 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
13394 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
13395
zhongyi3d4a55e72016-04-22 20:36:4613396 // Set up alternative service for server.
danakj1fd259a02016-04-16 03:17:0913397 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
bnc525e175a2016-06-20 12:36:4013398 HttpServerProperties* http_server_properties =
bnc5452e2a2015-05-08 16:27:4213399 session->http_server_properties();
13400 AlternativeService alternative_service(
bnca9b9e222016-07-11 20:10:4013401 AlternateProtocolFromNextProto(kProtoHTTP2), alternative);
bnc7dc7e1b42015-07-28 14:43:1213402 base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
zhongyi3d4a55e72016-04-22 20:36:4613403 http_server_properties->SetAlternativeService(server, alternative_service,
rchdc7b9052016-03-17 20:51:5013404 expiration);
bnc5452e2a2015-05-08 16:27:4213405
13406 // First transaction to alternative to open an HTTP/1.1 socket.
danakj1fd259a02016-04-16 03:17:0913407 std::unique_ptr<HttpTransaction> trans1(
bnc5452e2a2015-05-08 16:27:4213408 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13409 HttpRequestInfo request1;
13410 request1.method = "GET";
13411 request1.url = GURL(alternative_url);
13412 request1.load_flags = 0;
13413 TestCompletionCallback callback1;
13414
13415 int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113416 EXPECT_THAT(callback1.GetResult(rv), IsOk());
bnc5452e2a2015-05-08 16:27:4213417 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
13418 ASSERT_TRUE(response1);
wezca1070932016-05-26 20:30:5213419 ASSERT_TRUE(response1->headers);
bnc5452e2a2015-05-08 16:27:4213420 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
13421 EXPECT_TRUE(response1->was_npn_negotiated);
13422 EXPECT_FALSE(response1->was_fetched_via_spdy);
13423 std::string response_data1;
robpercival214763f2016-07-01 23:27:0113424 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
bnc5452e2a2015-05-08 16:27:4213425 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
13426
13427 // Request for origin.example.org, which has an alternative service. This
13428 // will start two Jobs: the alternative looks for connections to pool to,
13429 // finds one which is HTTP/1.1, and should ignore it, and should not try to
zhongyi3d4a55e72016-04-22 20:36:4613430 // open other connections to alternative server. The Job to server fails, so
bnc5452e2a2015-05-08 16:27:4213431 // this request fails.
danakj1fd259a02016-04-16 03:17:0913432 std::unique_ptr<HttpTransaction> trans2(
bnc5452e2a2015-05-08 16:27:4213433 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13434 HttpRequestInfo request2;
13435 request2.method = "GET";
13436 request2.url = GURL(origin_url);
13437 request2.load_flags = 0;
13438 TestCompletionCallback callback2;
13439
13440 rv = trans2->Start(&request2, callback2.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113441 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
bnc5452e2a2015-05-08 16:27:4213442
13443 // Another transaction to alternative. This is to test that the HTTP/1.1
13444 // socket is still open and in the pool.
danakj1fd259a02016-04-16 03:17:0913445 std::unique_ptr<HttpTransaction> trans3(
bnc5452e2a2015-05-08 16:27:4213446 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
13447 HttpRequestInfo request3;
13448 request3.method = "GET";
13449 request3.url = GURL(alternative_url);
13450 request3.load_flags = 0;
13451 TestCompletionCallback callback3;
13452
13453 rv = trans3->Start(&request3, callback3.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113454 EXPECT_THAT(callback3.GetResult(rv), IsOk());
bnc5452e2a2015-05-08 16:27:4213455 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13456 ASSERT_TRUE(response3);
wezca1070932016-05-26 20:30:5213457 ASSERT_TRUE(response3->headers);
bnc5452e2a2015-05-08 16:27:4213458 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
13459 EXPECT_TRUE(response3->was_npn_negotiated);
13460 EXPECT_FALSE(response3->was_fetched_via_spdy);
13461 std::string response_data3;
robpercival214763f2016-07-01 23:27:0113462 ASSERT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
bnc5452e2a2015-05-08 16:27:4213463 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
13464}
13465
bncd16676a2016-07-20 16:23:0113466TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
bncce36dca22015-04-21 22:11:2313467 const std::string https_url = "https://www.example.org:8080/";
13468 const std::string http_url = "http://www.example.org:8080/";
[email protected]8450d722012-07-02 19:14:0413469
rdsmithebb50aa2015-11-12 03:44:3813470 // Separate SPDY util instance for naked and wrapped requests.
bncd16676a2016-07-20 16:23:0113471 SpdyTestUtil spdy_util_wrapped;
rdsmithebb50aa2015-11-12 03:44:3813472
[email protected]8450d722012-07-02 19:14:0413473 // SPDY GET for HTTPS URL (through CONNECT tunnel)
bncce36dca22015-04-21 22:11:2313474 const HostPortPair host_port_pair("www.example.org", 8080);
bncdf80d44fd2016-07-15 20:27:4113475 SpdySerializedFrame connect(
lgarrona91df87f2014-12-05 00:51:3413476 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOWEST, host_port_pair));
bncdf80d44fd2016-07-15 20:27:4113477 SpdySerializedFrame req1(
bnc38dcd392016-02-09 23:19:4913478 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
bncdf80d44fd2016-07-15 20:27:4113479 SpdySerializedFrame wrapped_req1(
[email protected]23e482282013-06-14 16:08:0213480 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
[email protected]601e03f12014-04-06 16:26:3913481
13482 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
[email protected]745aa9c2014-06-27 02:21:2913483 SpdyHeaderBlock req2_block;
[email protected]745aa9c2014-06-27 02:21:2913484 req2_block[spdy_util_.GetMethodKey()] = "GET";
bncce36dca22015-04-21 22:11:2313485 req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080";
[email protected]745aa9c2014-06-27 02:21:2913486 req2_block[spdy_util_.GetSchemeKey()] = "http";
bnc7ecc1122015-09-28 13:22:4913487 req2_block[spdy_util_.GetPathKey()] = "/";
bncdf80d44fd2016-07-15 20:27:4113488 SpdySerializedFrame req2(
bnc42331402016-07-25 13:36:1513489 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
[email protected]8450d722012-07-02 19:14:0413490
13491 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4113492 CreateMockWrite(connect, 0), CreateMockWrite(wrapped_req1, 2),
13493 CreateMockWrite(req2, 6),
[email protected]8450d722012-07-02 19:14:0413494 };
13495
bncdf80d44fd2016-07-15 20:27:4113496 SpdySerializedFrame conn_resp(
bnc42331402016-07-25 13:36:1513497 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113498 SpdySerializedFrame resp1(
bnc42331402016-07-25 13:36:1513499 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113500 SpdySerializedFrame body1(spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
13501 SpdySerializedFrame wrapped_resp1(
rdsmithebb50aa2015-11-12 03:44:3813502 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
bncdf80d44fd2016-07-15 20:27:4113503 SpdySerializedFrame wrapped_body1(
rdsmithebb50aa2015-11-12 03:44:3813504 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
bnc42331402016-07-25 13:36:1513505 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3));
bncdf80d44fd2016-07-15 20:27:4113506 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
mmenke666a6fea2015-12-19 04:16:3313507 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4113508 CreateMockRead(conn_resp, 1),
mmenke666a6fea2015-12-19 04:16:3313509 MockRead(ASYNC, ERR_IO_PENDING, 3),
bncdf80d44fd2016-07-15 20:27:4113510 CreateMockRead(wrapped_resp1, 4),
13511 CreateMockRead(wrapped_body1, 5),
mmenke666a6fea2015-12-19 04:16:3313512 MockRead(ASYNC, ERR_IO_PENDING, 7),
bncdf80d44fd2016-07-15 20:27:4113513 CreateMockRead(resp2, 8),
13514 CreateMockRead(body2, 9),
mmenke666a6fea2015-12-19 04:16:3313515 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
13516 };
[email protected]8450d722012-07-02 19:14:0413517
mmenke666a6fea2015-12-19 04:16:3313518 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13519 arraysize(writes1));
[email protected]8450d722012-07-02 19:14:0413520 MockConnect connect_data1(ASYNC, OK);
[email protected]dd54bd82012-07-19 23:44:5713521 data1.set_connect_data(connect_data1);
[email protected]8450d722012-07-02 19:14:0413522
rdsmith82957ad2015-09-16 19:42:0313523 session_deps_.proxy_service =
13524 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70");
vishal.b62985ca92015-04-17 08:45:5113525 TestNetLog log;
[email protected]bb88e1d32013-05-03 23:11:0713526 session_deps_.net_log = &log;
[email protected]8450d722012-07-02 19:14:0413527 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3613528 ssl1.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3313529 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
[email protected]8450d722012-07-02 19:14:0413530 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3613531 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3313532 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13533 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]8450d722012-07-02 19:14:0413534
danakj1fd259a02016-04-16 03:17:0913535 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]8450d722012-07-02 19:14:0413536
13537 // Start the first transaction to set up the SpdySession
13538 HttpRequestInfo request1;
13539 request1.method = "GET";
13540 request1.url = GURL(https_url);
[email protected]8450d722012-07-02 19:14:0413541 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013542 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]8450d722012-07-02 19:14:0413543 TestCompletionCallback callback1;
mmenke666a6fea2015-12-19 04:16:3313544 int rv = trans1.Start(&request1, callback1.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413545
mmenke666a6fea2015-12-19 04:16:3313546 // This pause is a hack to avoid running into https://crbug.com/497228.
13547 data1.RunUntilPaused();
13548 base::RunLoop().RunUntilIdle();
13549 data1.Resume();
robpercival214763f2016-07-01 23:27:0113550 EXPECT_THAT(callback1.GetResult(rv), IsOk());
[email protected]8450d722012-07-02 19:14:0413551 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13552
[email protected]f6c63db52013-02-02 00:35:2213553 LoadTimingInfo load_timing_info1;
13554 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
13555 TestLoadTimingNotReusedWithPac(load_timing_info1,
13556 CONNECT_TIMING_HAS_SSL_TIMES);
13557
mmenke666a6fea2015-12-19 04:16:3313558 // Now, start the HTTP request.
[email protected]8450d722012-07-02 19:14:0413559 HttpRequestInfo request2;
13560 request2.method = "GET";
13561 request2.url = GURL(http_url);
[email protected]8450d722012-07-02 19:14:0413562 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013563 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]8450d722012-07-02 19:14:0413564 TestCompletionCallback callback2;
mmenke666a6fea2015-12-19 04:16:3313565 rv = trans2.Start(&request2, callback2.callback(), BoundNetLog());
[email protected]8450d722012-07-02 19:14:0413566
mmenke666a6fea2015-12-19 04:16:3313567 // This pause is a hack to avoid running into https://crbug.com/497228.
13568 data1.RunUntilPaused();
13569 base::RunLoop().RunUntilIdle();
13570 data1.Resume();
robpercival214763f2016-07-01 23:27:0113571 EXPECT_THAT(callback2.GetResult(rv), IsOk());
mmenke666a6fea2015-12-19 04:16:3313572
[email protected]8450d722012-07-02 19:14:0413573 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
[email protected]f6c63db52013-02-02 00:35:2213574
13575 LoadTimingInfo load_timing_info2;
13576 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
13577 // The established SPDY sessions is considered reused by the HTTP request.
13578 TestLoadTimingReusedWithPac(load_timing_info2);
13579 // HTTP requests over a SPDY session should have a different connection
13580 // socket_log_id than requests over a tunnel.
13581 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
[email protected]8450d722012-07-02 19:14:0413582}
13583
[email protected]2d88e7d2012-07-19 17:55:1713584// Test that in the case where we have a SPDY session to a SPDY proxy
13585// that we do not pool other origins that resolve to the same IP when
13586// the certificate does not match the new origin.
13587// http://crbug.com/134690
bncd16676a2016-07-20 16:23:0113588TEST_F(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
bncce36dca22015-04-21 22:11:2313589 const std::string url1 = "http://www.example.org/";
13590 const std::string url2 = "https://news.example.org/";
[email protected]2d88e7d2012-07-19 17:55:1713591 const std::string ip_addr = "1.2.3.4";
13592
rdsmithebb50aa2015-11-12 03:44:3813593 // Second SpdyTestUtil instance for the second socket.
bncd16676a2016-07-20 16:23:0113594 SpdyTestUtil spdy_util_secure;
rdsmithebb50aa2015-11-12 03:44:3813595
[email protected]2d88e7d2012-07-19 17:55:1713596 // SPDY GET for HTTP URL (through SPDY proxy)
bnc086b39e12016-06-24 13:05:2613597 SpdyHeaderBlock headers(
bncce36dca22015-04-21 22:11:2313598 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
bncdf80d44fd2016-07-15 20:27:4113599 SpdySerializedFrame req1(
bnc42331402016-07-25 13:36:1513600 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
[email protected]2d88e7d2012-07-19 17:55:1713601
13602 MockWrite writes1[] = {
bncdf80d44fd2016-07-15 20:27:4113603 CreateMockWrite(req1, 0),
[email protected]2d88e7d2012-07-19 17:55:1713604 };
13605
bnc42331402016-07-25 13:36:1513606 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113607 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]2d88e7d2012-07-19 17:55:1713608 MockRead reads1[] = {
bncdf80d44fd2016-07-15 20:27:4113609 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
13610 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
[email protected]2d88e7d2012-07-19 17:55:1713611 };
13612
mmenke666a6fea2015-12-19 04:16:3313613 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
13614 arraysize(writes1));
martijnfe9636e2016-02-06 14:33:3213615 IPAddress ip;
martijn654c8c42016-02-10 22:10:5913616 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
[email protected]2d88e7d2012-07-19 17:55:1713617 IPEndPoint peer_addr = IPEndPoint(ip, 443);
13618 MockConnect connect_data1(ASYNC, OK, peer_addr);
mmenke666a6fea2015-12-19 04:16:3313619 data1.set_connect_data(connect_data1);
[email protected]2d88e7d2012-07-19 17:55:1713620
13621 // SPDY GET for HTTPS URL (direct)
bncdf80d44fd2016-07-15 20:27:4113622 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4913623 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
[email protected]2d88e7d2012-07-19 17:55:1713624
13625 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4113626 CreateMockWrite(req2, 0),
[email protected]2d88e7d2012-07-19 17:55:1713627 };
13628
bnc42331402016-07-25 13:36:1513629 SpdySerializedFrame resp2(spdy_util_secure.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113630 SpdySerializedFrame body2(spdy_util_secure.ConstructSpdyDataFrame(1, true));
13631 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
mmenke666a6fea2015-12-19 04:16:3313632 MockRead(ASYNC, OK, 3)};
[email protected]2d88e7d2012-07-19 17:55:1713633
mmenke666a6fea2015-12-19 04:16:3313634 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13635 arraysize(writes2));
[email protected]2d88e7d2012-07-19 17:55:1713636 MockConnect connect_data2(ASYNC, OK);
mmenke666a6fea2015-12-19 04:16:3313637 data2.set_connect_data(connect_data2);
[email protected]2d88e7d2012-07-19 17:55:1713638
13639 // Set up a proxy config that sends HTTP requests to a proxy, and
13640 // all others direct.
13641 ProxyConfig proxy_config;
13642 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
[email protected]bb88e1d32013-05-03 23:11:0713643 session_deps_.proxy_service.reset(new ProxyService(
danakj1fd259a02016-04-16 03:17:0913644 base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)), nullptr,
csharrisonb7e3a082015-09-22 19:13:0413645 NULL));
[email protected]2d88e7d2012-07-19 17:55:1713646
bncce36dca22015-04-21 22:11:2313647 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
bnc3cf2a592016-08-11 14:48:3613648 ssl1.next_proto = kProtoHTTP2;
[email protected]2d88e7d2012-07-19 17:55:1713649 // Load a valid cert. Note, that this does not need to
13650 // be valid for proxy because the MockSSLClientSocket does
13651 // not actually verify it. But SpdySession will use this
13652 // to see if it is valid for the new origin
bncce36dca22015-04-21 22:11:2313653 ssl1.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
wezca1070932016-05-26 20:30:5213654 ASSERT_TRUE(ssl1.cert);
mmenke666a6fea2015-12-19 04:16:3313655 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13656 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]2d88e7d2012-07-19 17:55:1713657
13658 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
bnc3cf2a592016-08-11 14:48:3613659 ssl2.next_proto = kProtoHTTP2;
mmenke666a6fea2015-12-19 04:16:3313660 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13661 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]2d88e7d2012-07-19 17:55:1713662
[email protected]bb88e1d32013-05-03 23:11:0713663 session_deps_.host_resolver.reset(new MockCachingHostResolver());
bncce36dca22015-04-21 22:11:2313664 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
[email protected]bb88e1d32013-05-03 23:11:0713665 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
[email protected]2d88e7d2012-07-19 17:55:1713666
danakj1fd259a02016-04-16 03:17:0913667 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
[email protected]2d88e7d2012-07-19 17:55:1713668
13669 // Start the first transaction to set up the SpdySession
13670 HttpRequestInfo request1;
13671 request1.method = "GET";
13672 request1.url = GURL(url1);
[email protected]2d88e7d2012-07-19 17:55:1713673 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013674 HttpNetworkTransaction trans1(LOWEST, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713675 TestCompletionCallback callback1;
13676 ASSERT_EQ(ERR_IO_PENDING,
13677 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
mmenke666a6fea2015-12-19 04:16:3313678 // This pause is a hack to avoid running into https://crbug.com/497228.
13679 data1.RunUntilPaused();
13680 base::RunLoop().RunUntilIdle();
13681 data1.Resume();
[email protected]2d88e7d2012-07-19 17:55:1713682
robpercival214763f2016-07-01 23:27:0113683 EXPECT_THAT(callback1.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1713684 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
13685
13686 // Now, start the HTTP request
13687 HttpRequestInfo request2;
13688 request2.method = "GET";
13689 request2.url = GURL(url2);
[email protected]2d88e7d2012-07-19 17:55:1713690 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013691 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]2d88e7d2012-07-19 17:55:1713692 TestCompletionCallback callback2;
13693 EXPECT_EQ(ERR_IO_PENDING,
13694 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
fdoray92e35a72016-06-10 15:54:5513695 base::RunLoop().RunUntilIdle();
[email protected]2d88e7d2012-07-19 17:55:1713696
13697 ASSERT_TRUE(callback2.have_result());
robpercival214763f2016-07-01 23:27:0113698 EXPECT_THAT(callback2.WaitForResult(), IsOk());
[email protected]2d88e7d2012-07-19 17:55:1713699 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13700}
13701
[email protected]85f97342013-04-17 06:12:2413702// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
13703// error) in SPDY session, removes the socket from pool and closes the SPDY
13704// session. Verify that new url's from the same HttpNetworkSession (and a new
13705// SpdySession) do work. http://crbug.com/224701
bncd16676a2016-07-20 16:23:0113706TEST_F(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
bncce36dca22015-04-21 22:11:2313707 const std::string https_url = "https://www.example.org/";
[email protected]85f97342013-04-17 06:12:2413708
13709 MockRead reads1[] = {
13710 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
13711 };
13712
mmenke11eb5152015-06-09 14:50:5013713 SequencedSocketData data1(reads1, arraysize(reads1), NULL, 0);
[email protected]85f97342013-04-17 06:12:2413714
bncdf80d44fd2016-07-15 20:27:4113715 SpdySerializedFrame req2(
bnc38dcd392016-02-09 23:19:4913716 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
[email protected]85f97342013-04-17 06:12:2413717 MockWrite writes2[] = {
bncdf80d44fd2016-07-15 20:27:4113718 CreateMockWrite(req2, 0),
[email protected]85f97342013-04-17 06:12:2413719 };
13720
bnc42331402016-07-25 13:36:1513721 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113722 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]85f97342013-04-17 06:12:2413723 MockRead reads2[] = {
bncdf80d44fd2016-07-15 20:27:4113724 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
13725 MockRead(ASYNC, OK, 3) // EOF
[email protected]85f97342013-04-17 06:12:2413726 };
13727
mmenke11eb5152015-06-09 14:50:5013728 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
13729 arraysize(writes2));
[email protected]85f97342013-04-17 06:12:2413730
[email protected]85f97342013-04-17 06:12:2413731 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613732 ssl1.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5013733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13734 session_deps_.socket_factory->AddSocketDataProvider(&data1);
[email protected]85f97342013-04-17 06:12:2413735
13736 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613737 ssl2.next_proto = kProtoHTTP2;
mmenke11eb5152015-06-09 14:50:5013738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13739 session_deps_.socket_factory->AddSocketDataProvider(&data2);
[email protected]85f97342013-04-17 06:12:2413740
danakj1fd259a02016-04-16 03:17:0913741 std::unique_ptr<HttpNetworkSession> session(
mmenke11eb5152015-06-09 14:50:5013742 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
[email protected]85f97342013-04-17 06:12:2413743
13744 // Start the first transaction to set up the SpdySession and verify that
13745 // connection was closed.
13746 HttpRequestInfo request1;
13747 request1.method = "GET";
13748 request1.url = GURL(https_url);
13749 request1.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013750 HttpNetworkTransaction trans1(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413751 TestCompletionCallback callback1;
13752 EXPECT_EQ(ERR_IO_PENDING,
13753 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
robpercival214763f2016-07-01 23:27:0113754 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
[email protected]85f97342013-04-17 06:12:2413755
13756 // Now, start the second request and make sure it succeeds.
13757 HttpRequestInfo request2;
13758 request2.method = "GET";
13759 request2.url = GURL(https_url);
13760 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013761 HttpNetworkTransaction trans2(MEDIUM, session.get());
[email protected]85f97342013-04-17 06:12:2413762 TestCompletionCallback callback2;
13763 EXPECT_EQ(ERR_IO_PENDING,
13764 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
[email protected]85f97342013-04-17 06:12:2413765
robpercival214763f2016-07-01 23:27:0113766 ASSERT_THAT(callback2.WaitForResult(), IsOk());
[email protected]85f97342013-04-17 06:12:2413767 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
13768}
13769
bncd16676a2016-07-20 16:23:0113770TEST_F(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
[email protected]483fa202013-05-14 01:07:0313771 ClientSocketPoolManager::set_max_sockets_per_group(
13772 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13773 ClientSocketPoolManager::set_max_sockets_per_pool(
13774 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
13775
13776 // Use two different hosts with different IPs so they don't get pooled.
13777 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
13778 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
danakj1fd259a02016-04-16 03:17:0913779 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]483fa202013-05-14 01:07:0313780
13781 SSLSocketDataProvider ssl1(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613782 ssl1.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0313783 SSLSocketDataProvider ssl2(ASYNC, OK);
bnc3cf2a592016-08-11 14:48:3613784 ssl2.next_proto = kProtoHTTP2;
[email protected]483fa202013-05-14 01:07:0313785 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
13786 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
13787
bncdf80d44fd2016-07-15 20:27:4113788 SpdySerializedFrame host1_req(
bnc38dcd392016-02-09 23:19:4913789 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0313790 MockWrite spdy1_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113791 CreateMockWrite(host1_req, 0),
[email protected]483fa202013-05-14 01:07:0313792 };
bnc42331402016-07-25 13:36:1513793 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113794 SpdySerializedFrame host1_resp_body(
13795 spdy_util_.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313796 MockRead spdy1_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113797 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
mmenkee24011922015-12-17 22:12:5913798 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313799 };
13800
rdsmithebb50aa2015-11-12 03:44:3813801 // Use a separate test instance for the separate SpdySession that will be
13802 // created.
bncd16676a2016-07-20 16:23:0113803 SpdyTestUtil spdy_util_2;
danakj1fd259a02016-04-16 03:17:0913804 std::unique_ptr<SequencedSocketData> spdy1_data(
rch8e6c6c42015-05-01 14:05:1313805 new SequencedSocketData(spdy1_reads, arraysize(spdy1_reads), spdy1_writes,
13806 arraysize(spdy1_writes)));
[email protected]483fa202013-05-14 01:07:0313807 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
13808
bncdf80d44fd2016-07-15 20:27:4113809 SpdySerializedFrame host2_req(
bnc38dcd392016-02-09 23:19:4913810 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
[email protected]483fa202013-05-14 01:07:0313811 MockWrite spdy2_writes[] = {
bncdf80d44fd2016-07-15 20:27:4113812 CreateMockWrite(host2_req, 0),
[email protected]483fa202013-05-14 01:07:0313813 };
bnc42331402016-07-25 13:36:1513814 SpdySerializedFrame host2_resp(spdy_util_2.ConstructSpdyGetReply(NULL, 0, 1));
bncdf80d44fd2016-07-15 20:27:4113815 SpdySerializedFrame host2_resp_body(
13816 spdy_util_2.ConstructSpdyDataFrame(1, true));
[email protected]483fa202013-05-14 01:07:0313817 MockRead spdy2_reads[] = {
bncdf80d44fd2016-07-15 20:27:4113818 CreateMockRead(host2_resp, 1), CreateMockRead(host2_resp_body, 2),
mmenkee24011922015-12-17 22:12:5913819 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
[email protected]483fa202013-05-14 01:07:0313820 };
13821
danakj1fd259a02016-04-16 03:17:0913822 std::unique_ptr<SequencedSocketData> spdy2_data(
rch8e6c6c42015-05-01 14:05:1313823 new SequencedSocketData(spdy2_reads, arraysize(spdy2_reads), spdy2_writes,
13824 arraysize(spdy2_writes)));
[email protected]483fa202013-05-14 01:07:0313825 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
13826
13827 MockWrite http_write[] = {
13828 MockWrite("GET / HTTP/1.1\r\n"
13829 "Host: www.a.com\r\n"
13830 "Connection: keep-alive\r\n\r\n"),
13831 };
13832
13833 MockRead http_read[] = {
13834 MockRead("HTTP/1.1 200 OK\r\n"),
13835 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13836 MockRead("Content-Length: 6\r\n\r\n"),
13837 MockRead("hello!"),
13838 };
13839 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
13840 http_write, arraysize(http_write));
13841 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
13842
13843 HostPortPair host_port_pair_a("www.a.com", 443);
[email protected]e6d017652013-05-17 18:01:4013844 SpdySessionKey spdy_session_key_a(
[email protected]314b03992014-04-01 01:28:5313845 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313846 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613847 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313848
13849 TestCompletionCallback callback;
13850 HttpRequestInfo request1;
13851 request1.method = "GET";
13852 request1.url = GURL("https://www.a.com/");
13853 request1.load_flags = 0;
danakj1fd259a02016-04-16 03:17:0913854 std::unique_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:5013855 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313856
13857 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13859 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0313860
13861 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213862 ASSERT_TRUE(response);
13863 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213864 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0313865 EXPECT_TRUE(response->was_fetched_via_spdy);
13866 EXPECT_TRUE(response->was_npn_negotiated);
13867
13868 std::string response_data;
robpercival214763f2016-07-01 23:27:0113869 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0313870 EXPECT_EQ("hello!", response_data);
13871 trans.reset();
13872 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2613873 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313874
13875 HostPortPair host_port_pair_b("www.b.com", 443);
[email protected]e6d017652013-05-17 18:01:4013876 SpdySessionKey spdy_session_key_b(
[email protected]314b03992014-04-01 01:28:5313877 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313878 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613879 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313880 HttpRequestInfo request2;
13881 request2.method = "GET";
13882 request2.url = GURL("https://www.b.com/");
13883 request2.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013884 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313885
13886 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113887 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13888 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0313889
13890 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213891 ASSERT_TRUE(response);
13892 ASSERT_TRUE(response->headers);
bnc84e7fb52015-12-02 11:50:0213893 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
[email protected]483fa202013-05-14 01:07:0313894 EXPECT_TRUE(response->was_fetched_via_spdy);
13895 EXPECT_TRUE(response->was_npn_negotiated);
robpercival214763f2016-07-01 23:27:0113896 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0313897 EXPECT_EQ("hello!", response_data);
13898 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613899 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313900 EXPECT_TRUE(
[email protected]41d64e82013-07-03 22:44:2613901 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313902
13903 HostPortPair host_port_pair_a1("www.a.com", 80);
[email protected]e6d017652013-05-17 18:01:4013904 SpdySessionKey spdy_session_key_a1(
[email protected]314b03992014-04-01 01:28:5313905 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]483fa202013-05-14 01:07:0313906 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613907 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
[email protected]483fa202013-05-14 01:07:0313908 HttpRequestInfo request3;
13909 request3.method = "GET";
13910 request3.url = GURL("http://www.a.com/");
13911 request3.load_flags = 0;
[email protected]90499482013-06-01 00:39:5013912 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]483fa202013-05-14 01:07:0313913
13914 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113915 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13916 EXPECT_THAT(callback.WaitForResult(), IsOk());
[email protected]483fa202013-05-14 01:07:0313917
13918 response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5213919 ASSERT_TRUE(response);
13920 ASSERT_TRUE(response->headers);
[email protected]483fa202013-05-14 01:07:0313921 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13922 EXPECT_FALSE(response->was_fetched_via_spdy);
13923 EXPECT_FALSE(response->was_npn_negotiated);
robpercival214763f2016-07-01 23:27:0113924 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
[email protected]483fa202013-05-14 01:07:0313925 EXPECT_EQ("hello!", response_data);
13926 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613927 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
[email protected]483fa202013-05-14 01:07:0313928 EXPECT_FALSE(
[email protected]41d64e82013-07-03 22:44:2613929 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
[email protected]483fa202013-05-14 01:07:0313930}
13931
bncd16676a2016-07-20 16:23:0113932TEST_F(HttpNetworkTransactionTest, HttpSyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0413933 HttpRequestInfo request;
13934 request.method = "GET";
bncce36dca22015-04-21 22:11:2313935 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413936 request.load_flags = 0;
13937
danakj1fd259a02016-04-16 03:17:0913938 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13939 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113940 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413941
ttuttled9dbc652015-09-29 20:00:5913942 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0413943 StaticSocketDataProvider data;
13944 data.set_connect_data(mock_connect);
13945 session_deps_.socket_factory->AddSocketDataProvider(&data);
13946
13947 TestCompletionCallback callback;
13948
13949 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113950 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0413951
13952 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0113953 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0413954
[email protected]79e1fd62013-06-20 06:50:0413955 // We don't care whether this succeeds or fails, but it shouldn't crash.
13956 HttpRequestHeaders request_headers;
13957 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4713958
13959 ConnectionAttempts attempts;
13960 trans->GetConnectionAttempts(&attempts);
13961 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0113962 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5913963
13964 IPEndPoint endpoint;
13965 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
13966 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0413967}
13968
bncd16676a2016-07-20 16:23:0113969TEST_F(HttpNetworkTransactionTest, HttpAsyncConnectError) {
[email protected]79e1fd62013-06-20 06:50:0413970 HttpRequestInfo request;
13971 request.method = "GET";
bncce36dca22015-04-21 22:11:2313972 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0413973 request.load_flags = 0;
13974
danakj1fd259a02016-04-16 03:17:0913975 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13976 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4113977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0413978
ttuttled9dbc652015-09-29 20:00:5913979 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
[email protected]79e1fd62013-06-20 06:50:0413980 StaticSocketDataProvider data;
13981 data.set_connect_data(mock_connect);
13982 session_deps_.socket_factory->AddSocketDataProvider(&data);
13983
13984 TestCompletionCallback callback;
13985
13986 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0113987 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0413988
13989 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0113990 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
[email protected]79e1fd62013-06-20 06:50:0413991
[email protected]79e1fd62013-06-20 06:50:0413992 // We don't care whether this succeeds or fails, but it shouldn't crash.
13993 HttpRequestHeaders request_headers;
13994 trans->GetFullRequestHeaders(&request_headers);
ttuttle1f2d7e92015-04-28 16:17:4713995
13996 ConnectionAttempts attempts;
13997 trans->GetConnectionAttempts(&attempts);
13998 ASSERT_EQ(1u, attempts.size());
robpercival214763f2016-07-01 23:27:0113999 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
ttuttled9dbc652015-09-29 20:00:5914000
14001 IPEndPoint endpoint;
14002 EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
14003 EXPECT_TRUE(endpoint.address().empty());
[email protected]79e1fd62013-06-20 06:50:0414004}
14005
bncd16676a2016-07-20 16:23:0114006TEST_F(HttpNetworkTransactionTest, HttpSyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0414007 HttpRequestInfo request;
14008 request.method = "GET";
bncce36dca22015-04-21 22:11:2314009 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414010 request.load_flags = 0;
14011
danakj1fd259a02016-04-16 03:17:0914012 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14013 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114014 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414015
14016 MockWrite data_writes[] = {
14017 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14018 };
14019 MockRead data_reads[] = {
14020 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14021 };
14022
14023 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14024 data_writes, arraysize(data_writes));
14025 session_deps_.socket_factory->AddSocketDataProvider(&data);
14026
14027 TestCompletionCallback callback;
14028
14029 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114030 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0414031
14032 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114033 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0414034
[email protected]79e1fd62013-06-20 06:50:0414035 HttpRequestHeaders request_headers;
14036 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14037 EXPECT_TRUE(request_headers.HasHeader("Host"));
14038}
14039
bncd16676a2016-07-20 16:23:0114040TEST_F(HttpNetworkTransactionTest, HttpAsyncWriteError) {
[email protected]79e1fd62013-06-20 06:50:0414041 HttpRequestInfo request;
14042 request.method = "GET";
bncce36dca22015-04-21 22:11:2314043 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414044 request.load_flags = 0;
14045
danakj1fd259a02016-04-16 03:17:0914046 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14047 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114048 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414049
14050 MockWrite data_writes[] = {
14051 MockWrite(ASYNC, ERR_CONNECTION_RESET),
14052 };
14053 MockRead data_reads[] = {
14054 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
14055 };
14056
14057 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14058 data_writes, arraysize(data_writes));
14059 session_deps_.socket_factory->AddSocketDataProvider(&data);
14060
14061 TestCompletionCallback callback;
14062
14063 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114064 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0414065
14066 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114067 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0414068
[email protected]79e1fd62013-06-20 06:50:0414069 HttpRequestHeaders request_headers;
14070 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14071 EXPECT_TRUE(request_headers.HasHeader("Host"));
14072}
14073
bncd16676a2016-07-20 16:23:0114074TEST_F(HttpNetworkTransactionTest, HttpSyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0414075 HttpRequestInfo request;
14076 request.method = "GET";
bncce36dca22015-04-21 22:11:2314077 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414078 request.load_flags = 0;
14079
danakj1fd259a02016-04-16 03:17:0914080 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14081 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114082 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414083
14084 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314085 MockWrite(
14086 "GET / HTTP/1.1\r\n"
14087 "Host: www.example.org\r\n"
14088 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414089 };
14090 MockRead data_reads[] = {
14091 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
14092 };
14093
14094 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14095 data_writes, arraysize(data_writes));
14096 session_deps_.socket_factory->AddSocketDataProvider(&data);
14097
14098 TestCompletionCallback callback;
14099
14100 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114101 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0414102
14103 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114104 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0414105
[email protected]79e1fd62013-06-20 06:50:0414106 HttpRequestHeaders request_headers;
14107 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14108 EXPECT_TRUE(request_headers.HasHeader("Host"));
14109}
14110
bncd16676a2016-07-20 16:23:0114111TEST_F(HttpNetworkTransactionTest, HttpAsyncReadError) {
[email protected]79e1fd62013-06-20 06:50:0414112 HttpRequestInfo request;
14113 request.method = "GET";
bncce36dca22015-04-21 22:11:2314114 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414115 request.load_flags = 0;
14116
danakj1fd259a02016-04-16 03:17:0914117 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14118 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114119 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414120
14121 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314122 MockWrite(
14123 "GET / HTTP/1.1\r\n"
14124 "Host: www.example.org\r\n"
14125 "Connection: keep-alive\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414126 };
14127 MockRead data_reads[] = {
14128 MockRead(ASYNC, ERR_CONNECTION_RESET),
14129 };
14130
14131 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14132 data_writes, arraysize(data_writes));
14133 session_deps_.socket_factory->AddSocketDataProvider(&data);
14134
14135 TestCompletionCallback callback;
14136
14137 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114138 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0414139
14140 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114141 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]79e1fd62013-06-20 06:50:0414142
[email protected]79e1fd62013-06-20 06:50:0414143 HttpRequestHeaders request_headers;
14144 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14145 EXPECT_TRUE(request_headers.HasHeader("Host"));
14146}
14147
bncd16676a2016-07-20 16:23:0114148TEST_F(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
[email protected]79e1fd62013-06-20 06:50:0414149 HttpRequestInfo request;
14150 request.method = "GET";
bncce36dca22015-04-21 22:11:2314151 request.url = GURL("http://www.example.org/");
[email protected]79e1fd62013-06-20 06:50:0414152 request.load_flags = 0;
14153 request.extra_headers.SetHeader("X-Foo", "bar");
14154
danakj1fd259a02016-04-16 03:17:0914155 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14156 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114157 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]79e1fd62013-06-20 06:50:0414158
14159 MockWrite data_writes[] = {
bncce36dca22015-04-21 22:11:2314160 MockWrite(
14161 "GET / HTTP/1.1\r\n"
14162 "Host: www.example.org\r\n"
14163 "Connection: keep-alive\r\n"
14164 "X-Foo: bar\r\n\r\n"),
[email protected]79e1fd62013-06-20 06:50:0414165 };
14166 MockRead data_reads[] = {
14167 MockRead("HTTP/1.1 200 OK\r\n"
14168 "Content-Length: 5\r\n\r\n"
14169 "hello"),
14170 MockRead(ASYNC, ERR_UNEXPECTED),
14171 };
14172
14173 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
14174 data_writes, arraysize(data_writes));
14175 session_deps_.socket_factory->AddSocketDataProvider(&data);
14176
14177 TestCompletionCallback callback;
14178
14179 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114180 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]79e1fd62013-06-20 06:50:0414181
14182 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114183 EXPECT_THAT(rv, IsOk());
[email protected]79e1fd62013-06-20 06:50:0414184
14185 HttpRequestHeaders request_headers;
14186 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
14187 std::string foo;
14188 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
14189 EXPECT_EQ("bar", foo);
14190}
14191
[email protected]bf828982013-08-14 18:01:4714192namespace {
14193
yhiranoa7e05bb2014-11-06 05:40:3914194// Fake HttpStream that simply records calls to SetPriority().
14195class FakeStream : public HttpStream,
[email protected]e86839fd2013-08-14 18:29:0314196 public base::SupportsWeakPtr<FakeStream> {
14197 public:
14198 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
dchengb03027d2014-10-21 12:00:2014199 ~FakeStream() override {}
[email protected]e86839fd2013-08-14 18:29:0314200
14201 RequestPriority priority() const { return priority_; }
14202
dchengb03027d2014-10-21 12:00:2014203 int InitializeStream(const HttpRequestInfo* request_info,
14204 RequestPriority priority,
14205 const BoundNetLog& net_log,
14206 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314207 return ERR_IO_PENDING;
14208 }
14209
dchengb03027d2014-10-21 12:00:2014210 int SendRequest(const HttpRequestHeaders& request_headers,
14211 HttpResponseInfo* response,
14212 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314213 ADD_FAILURE();
14214 return ERR_UNEXPECTED;
14215 }
14216
dchengb03027d2014-10-21 12:00:2014217 int ReadResponseHeaders(const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314218 ADD_FAILURE();
14219 return ERR_UNEXPECTED;
14220 }
14221
dchengb03027d2014-10-21 12:00:2014222 int ReadResponseBody(IOBuffer* buf,
14223 int buf_len,
14224 const CompletionCallback& callback) override {
[email protected]e86839fd2013-08-14 18:29:0314225 ADD_FAILURE();
14226 return ERR_UNEXPECTED;
14227 }
14228
dchengb03027d2014-10-21 12:00:2014229 void Close(bool not_reusable) override {}
[email protected]e86839fd2013-08-14 18:29:0314230
dchengb03027d2014-10-21 12:00:2014231 bool IsResponseBodyComplete() const override {
[email protected]e86839fd2013-08-14 18:29:0314232 ADD_FAILURE();
14233 return false;
14234 }
14235
dchengb03027d2014-10-21 12:00:2014236 bool IsConnectionReused() const override {
[email protected]e86839fd2013-08-14 18:29:0314237 ADD_FAILURE();
14238 return false;
14239 }
14240
dchengb03027d2014-10-21 12:00:2014241 void SetConnectionReused() override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314242
mmenkebd84c392015-09-02 14:12:3414243 bool CanReuseConnection() const override { return false; }
[email protected]e86839fd2013-08-14 18:29:0314244
sclittle4de1bab92015-09-22 21:28:2414245 int64_t GetTotalReceivedBytes() const override {
[email protected]bc92bc972013-12-13 08:32:5914246 ADD_FAILURE();
14247 return 0;
14248 }
14249
sclittlebe1ccf62015-09-02 19:40:3614250 int64_t GetTotalSentBytes() const override {
14251 ADD_FAILURE();
14252 return 0;
14253 }
14254
dchengb03027d2014-10-21 12:00:2014255 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
[email protected]e86839fd2013-08-14 18:29:0314256 ADD_FAILURE();
14257 return false;
14258 }
14259
dchengb03027d2014-10-21 12:00:2014260 void GetSSLInfo(SSLInfo* ssl_info) override { ADD_FAILURE(); }
14261
14262 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
[email protected]e86839fd2013-08-14 18:29:0314263 ADD_FAILURE();
14264 }
14265
ttuttled9dbc652015-09-29 20:00:5914266 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14267
nharperb7441ef2016-01-25 23:54:1414268 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14269 std::vector<uint8_t>* out) override {
14270 ADD_FAILURE();
14271 return ERR_NOT_IMPLEMENTED;
14272 }
14273
dchengb03027d2014-10-21 12:00:2014274 void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
[email protected]e86839fd2013-08-14 18:29:0314275
zhongyica364fbb2015-12-12 03:39:1214276 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14277
dchengb03027d2014-10-21 12:00:2014278 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]e86839fd2013-08-14 18:29:0314279
yhiranoa7e05bb2014-11-06 05:40:3914280 UploadProgress GetUploadProgress() const override { return UploadProgress(); }
14281
14282 HttpStream* RenewStreamForAuth() override { return NULL; }
14283
[email protected]e86839fd2013-08-14 18:29:0314284 private:
14285 RequestPriority priority_;
14286
14287 DISALLOW_COPY_AND_ASSIGN(FakeStream);
14288};
14289
14290// Fake HttpStreamRequest that simply records calls to SetPriority()
14291// and vends FakeStreams with its current priority.
[email protected]bf828982013-08-14 18:01:4714292class FakeStreamRequest : public HttpStreamRequest,
14293 public base::SupportsWeakPtr<FakeStreamRequest> {
14294 public:
[email protected]e86839fd2013-08-14 18:29:0314295 FakeStreamRequest(RequestPriority priority,
14296 HttpStreamRequest::Delegate* delegate)
14297 : priority_(priority),
[email protected]831e4a32013-11-14 02:14:4414298 delegate_(delegate),
14299 websocket_stream_create_helper_(NULL) {}
14300
14301 FakeStreamRequest(RequestPriority priority,
14302 HttpStreamRequest::Delegate* delegate,
14303 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
14304 : priority_(priority),
14305 delegate_(delegate),
14306 websocket_stream_create_helper_(create_helper) {}
[email protected]e86839fd2013-08-14 18:29:0314307
dchengb03027d2014-10-21 12:00:2014308 ~FakeStreamRequest() override {}
[email protected]bf828982013-08-14 18:01:4714309
14310 RequestPriority priority() const { return priority_; }
14311
[email protected]831e4a32013-11-14 02:14:4414312 const WebSocketHandshakeStreamBase::CreateHelper*
14313 websocket_stream_create_helper() const {
14314 return websocket_stream_create_helper_;
14315 }
14316
[email protected]e86839fd2013-08-14 18:29:0314317 // Create a new FakeStream and pass it to the request's
14318 // delegate. Returns a weak pointer to the FakeStream.
14319 base::WeakPtr<FakeStream> FinishStreamRequest() {
14320 FakeStream* fake_stream = new FakeStream(priority_);
14321 // Do this before calling OnStreamReady() as OnStreamReady() may
14322 // immediately delete |fake_stream|.
14323 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
14324 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
14325 return weak_stream;
14326 }
14327
dchengb03027d2014-10-21 12:00:2014328 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override {
[email protected]bf828982013-08-14 18:01:4714329 ADD_FAILURE();
14330 return ERR_UNEXPECTED;
14331 }
14332
dchengb03027d2014-10-21 12:00:2014333 LoadState GetLoadState() const override {
[email protected]bf828982013-08-14 18:01:4714334 ADD_FAILURE();
14335 return LoadState();
14336 }
14337
dchengb03027d2014-10-21 12:00:2014338 void SetPriority(RequestPriority priority) override { priority_ = priority; }
[email protected]bf828982013-08-14 18:01:4714339
dchengb03027d2014-10-21 12:00:2014340 bool was_npn_negotiated() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714341
dchengb03027d2014-10-21 12:00:2014342 NextProto protocol_negotiated() const override { return kProtoUnknown; }
[email protected]bf828982013-08-14 18:01:4714343
dchengb03027d2014-10-21 12:00:2014344 bool using_spdy() const override { return false; }
[email protected]bf828982013-08-14 18:01:4714345
ttuttle1f2d7e92015-04-28 16:17:4714346 const ConnectionAttempts& connection_attempts() const override {
14347 static ConnectionAttempts no_attempts;
14348 return no_attempts;
14349 }
14350
[email protected]bf828982013-08-14 18:01:4714351 private:
14352 RequestPriority priority_;
[email protected]e86839fd2013-08-14 18:29:0314353 HttpStreamRequest::Delegate* const delegate_;
[email protected]831e4a32013-11-14 02:14:4414354 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
[email protected]bf828982013-08-14 18:01:4714355
14356 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
14357};
14358
14359// Fake HttpStreamFactory that vends FakeStreamRequests.
14360class FakeStreamFactory : public HttpStreamFactory {
14361 public:
14362 FakeStreamFactory() {}
dchengb03027d2014-10-21 12:00:2014363 ~FakeStreamFactory() override {}
[email protected]bf828982013-08-14 18:01:4714364
14365 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
14366 // RequestStream() (which may be NULL if it was destroyed already).
14367 base::WeakPtr<FakeStreamRequest> last_stream_request() {
14368 return last_stream_request_;
14369 }
14370
dchengb03027d2014-10-21 12:00:2014371 HttpStreamRequest* RequestStream(const HttpRequestInfo& info,
14372 RequestPriority priority,
14373 const SSLConfig& server_ssl_config,
14374 const SSLConfig& proxy_ssl_config,
14375 HttpStreamRequest::Delegate* delegate,
14376 const BoundNetLog& net_log) override {
[email protected]e86839fd2013-08-14 18:29:0314377 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
[email protected]bf828982013-08-14 18:01:4714378 last_stream_request_ = fake_request->AsWeakPtr();
14379 return fake_request;
14380 }
14381
xunjieli5749218c2016-03-22 16:43:0614382 HttpStreamRequest* RequestBidirectionalStreamImpl(
xunjieli11834f02015-12-22 04:27:0814383 const HttpRequestInfo& info,
14384 RequestPriority priority,
14385 const SSLConfig& server_ssl_config,
14386 const SSLConfig& proxy_ssl_config,
14387 HttpStreamRequest::Delegate* delegate,
14388 const BoundNetLog& net_log) override {
14389 NOTREACHED();
14390 return nullptr;
14391 }
14392
dchengb03027d2014-10-21 12:00:2014393 HttpStreamRequest* RequestWebSocketHandshakeStream(
[email protected]bf828982013-08-14 18:01:4714394 const HttpRequestInfo& info,
14395 RequestPriority priority,
14396 const SSLConfig& server_ssl_config,
14397 const SSLConfig& proxy_ssl_config,
14398 HttpStreamRequest::Delegate* delegate,
[email protected]467086b2013-11-12 08:19:4614399 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
mostynbba063d6032014-10-09 11:01:1314400 const BoundNetLog& net_log) override {
[email protected]831e4a32013-11-14 02:14:4414401 FakeStreamRequest* fake_request =
14402 new FakeStreamRequest(priority, delegate, create_helper);
14403 last_stream_request_ = fake_request->AsWeakPtr();
14404 return fake_request;
[email protected]bf828982013-08-14 18:01:4714405 }
14406
dchengb03027d2014-10-21 12:00:2014407 void PreconnectStreams(int num_streams,
nharper8cdb0fb2016-04-22 21:34:5914408 const HttpRequestInfo& info) override {
[email protected]bf828982013-08-14 18:01:4714409 ADD_FAILURE();
14410 }
14411
dchengb03027d2014-10-21 12:00:2014412 const HostMappingRules* GetHostMappingRules() const override {
[email protected]bf828982013-08-14 18:01:4714413 ADD_FAILURE();
14414 return NULL;
14415 }
14416
14417 private:
14418 base::WeakPtr<FakeStreamRequest> last_stream_request_;
14419
14420 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
14421};
14422
Adam Rice425cf122015-01-19 06:18:2414423// TODO(ricea): Maybe unify this with the one in
14424// url_request_http_job_unittest.cc ?
14425class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
14426 public:
danakj1fd259a02016-04-16 03:17:0914427 FakeWebSocketBasicHandshakeStream(
14428 std::unique_ptr<ClientSocketHandle> connection,
14429 bool using_proxy)
Adam Rice425cf122015-01-19 06:18:2414430 : state_(connection.release(), using_proxy) {}
14431
14432 // Fake implementation of HttpStreamBase methods.
14433 // This ends up being quite "real" because this object has to really send data
14434 // on the mock socket. It might be easier to use the real implementation, but
14435 // the fact that the WebSocket code is not compiled on iOS makes that
14436 // difficult.
14437 int InitializeStream(const HttpRequestInfo* request_info,
14438 RequestPriority priority,
14439 const BoundNetLog& net_log,
14440 const CompletionCallback& callback) override {
14441 state_.Initialize(request_info, priority, net_log, callback);
14442 return OK;
14443 }
14444
14445 int SendRequest(const HttpRequestHeaders& request_headers,
14446 HttpResponseInfo* response,
14447 const CompletionCallback& callback) override {
14448 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers,
14449 response, callback);
14450 }
14451
14452 int ReadResponseHeaders(const CompletionCallback& callback) override {
14453 return parser()->ReadResponseHeaders(callback);
14454 }
14455
14456 int ReadResponseBody(IOBuffer* buf,
14457 int buf_len,
14458 const CompletionCallback& callback) override {
14459 NOTREACHED();
14460 return ERR_IO_PENDING;
14461 }
14462
14463 void Close(bool not_reusable) override {
14464 if (parser())
14465 parser()->Close(true);
14466 }
14467
14468 bool IsResponseBodyComplete() const override {
14469 NOTREACHED();
14470 return false;
14471 }
14472
Adam Rice425cf122015-01-19 06:18:2414473 bool IsConnectionReused() const override {
14474 NOTREACHED();
14475 return false;
14476 }
14477 void SetConnectionReused() override { NOTREACHED(); }
14478
mmenkebd84c392015-09-02 14:12:3414479 bool CanReuseConnection() const override { return false; }
Adam Rice425cf122015-01-19 06:18:2414480
sclittle4de1bab92015-09-22 21:28:2414481 int64_t GetTotalReceivedBytes() const override {
Adam Rice425cf122015-01-19 06:18:2414482 NOTREACHED();
14483 return 0;
14484 }
14485
sclittlebe1ccf62015-09-02 19:40:3614486 int64_t GetTotalSentBytes() const override {
14487 NOTREACHED();
14488 return 0;
14489 }
14490
Adam Rice425cf122015-01-19 06:18:2414491 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
14492 NOTREACHED();
14493 return false;
14494 }
14495
Adam Ricecb76ac62015-02-20 05:33:2514496 void GetSSLInfo(SSLInfo* ssl_info) override {}
Adam Rice425cf122015-01-19 06:18:2414497
14498 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {
14499 NOTREACHED();
14500 }
14501
ttuttled9dbc652015-09-29 20:00:5914502 bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
14503
nharperb7441ef2016-01-25 23:54:1414504 Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
14505 std::vector<uint8_t>* out) override {
14506 ADD_FAILURE();
14507 return ERR_NOT_IMPLEMENTED;
14508 }
14509
Adam Rice425cf122015-01-19 06:18:2414510 void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
14511
zhongyica364fbb2015-12-12 03:39:1214512 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
14513
Adam Rice425cf122015-01-19 06:18:2414514 void SetPriority(RequestPriority priority) override { NOTREACHED(); }
14515
14516 UploadProgress GetUploadProgress() const override {
14517 NOTREACHED();
14518 return UploadProgress();
14519 }
14520
14521 HttpStream* RenewStreamForAuth() override {
14522 NOTREACHED();
14523 return nullptr;
14524 }
14525
14526 // Fake implementation of WebSocketHandshakeStreamBase method(s)
danakj1fd259a02016-04-16 03:17:0914527 std::unique_ptr<WebSocketStream> Upgrade() override {
Adam Rice425cf122015-01-19 06:18:2414528 NOTREACHED();
danakj1fd259a02016-04-16 03:17:0914529 return std::unique_ptr<WebSocketStream>();
Adam Rice425cf122015-01-19 06:18:2414530 }
14531
14532 private:
14533 HttpStreamParser* parser() const { return state_.parser(); }
14534 HttpBasicState state_;
14535
14536 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream);
14537};
14538
[email protected]831e4a32013-11-14 02:14:4414539// TODO(yhirano): Split this class out into a net/websockets file, if it is
14540// worth doing.
14541class FakeWebSocketStreamCreateHelper :
14542 public WebSocketHandshakeStreamBase::CreateHelper {
14543 public:
dchengb03027d2014-10-21 12:00:2014544 WebSocketHandshakeStreamBase* CreateBasicStream(
danakj1fd259a02016-04-16 03:17:0914545 std::unique_ptr<ClientSocketHandle> connection,
mostynbba063d6032014-10-09 11:01:1314546 bool using_proxy) override {
dchengc7eeda422015-12-26 03:56:4814547 return new FakeWebSocketBasicHandshakeStream(std::move(connection),
Adam Rice425cf122015-01-19 06:18:2414548 using_proxy);
[email protected]831e4a32013-11-14 02:14:4414549 }
14550
dchengb03027d2014-10-21 12:00:2014551 WebSocketHandshakeStreamBase* CreateSpdyStream(
[email protected]831e4a32013-11-14 02:14:4414552 const base::WeakPtr<SpdySession>& session,
mostynbba063d6032014-10-09 11:01:1314553 bool use_relative_url) override {
[email protected]831e4a32013-11-14 02:14:4414554 NOTREACHED();
14555 return NULL;
14556 };
14557
dchengb03027d2014-10-21 12:00:2014558 ~FakeWebSocketStreamCreateHelper() override {}
[email protected]831e4a32013-11-14 02:14:4414559
danakj1fd259a02016-04-16 03:17:0914560 virtual std::unique_ptr<WebSocketStream> Upgrade() {
[email protected]831e4a32013-11-14 02:14:4414561 NOTREACHED();
danakj1fd259a02016-04-16 03:17:0914562 return std::unique_ptr<WebSocketStream>();
[email protected]831e4a32013-11-14 02:14:4414563 }
14564};
14565
[email protected]bf828982013-08-14 18:01:4714566} // namespace
14567
14568// Make sure that HttpNetworkTransaction passes on its priority to its
14569// stream request on start.
bncd16676a2016-07-20 16:23:0114570TEST_F(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
danakj1fd259a02016-04-16 03:17:0914571 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenkee65e7af2015-10-13 17:16:4214572 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714573 FakeStreamFactory* fake_factory = new FakeStreamFactory();
danakj1fd259a02016-04-16 03:17:0914574 peer.SetHttpStreamFactory(std::unique_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714575
dcheng48459ac22014-08-26 00:46:4114576 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714577
wezca1070932016-05-26 20:30:5214578 ASSERT_FALSE(fake_factory->last_stream_request());
[email protected]bf828982013-08-14 18:01:4714579
14580 HttpRequestInfo request;
14581 TestCompletionCallback callback;
14582 EXPECT_EQ(ERR_IO_PENDING,
14583 trans.Start(&request, callback.callback(), BoundNetLog()));
14584
14585 base::WeakPtr<FakeStreamRequest> fake_request =
14586 fake_factory->last_stream_request();
wezca1070932016-05-26 20:30:5214587 ASSERT_TRUE(fake_request);
[email protected]bf828982013-08-14 18:01:4714588 EXPECT_EQ(LOW, fake_request->priority());
14589}
14590
14591// Make sure that HttpNetworkTransaction passes on its priority
14592// updates to its stream request.
bncd16676a2016-07-20 16:23:0114593TEST_F(HttpNetworkTransactionTest, SetStreamRequestPriority) {
danakj1fd259a02016-04-16 03:17:0914594 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenkee65e7af2015-10-13 17:16:4214595 HttpNetworkSessionPeer peer(session.get());
[email protected]bf828982013-08-14 18:01:4714596 FakeStreamFactory* fake_factory = new FakeStreamFactory();
danakj1fd259a02016-04-16 03:17:0914597 peer.SetHttpStreamFactory(std::unique_ptr<HttpStreamFactory>(fake_factory));
[email protected]bf828982013-08-14 18:01:4714598
dcheng48459ac22014-08-26 00:46:4114599 HttpNetworkTransaction trans(LOW, session.get());
[email protected]bf828982013-08-14 18:01:4714600
14601 HttpRequestInfo request;
14602 TestCompletionCallback callback;
14603 EXPECT_EQ(ERR_IO_PENDING,
14604 trans.Start(&request, callback.callback(), BoundNetLog()));
14605
14606 base::WeakPtr<FakeStreamRequest> fake_request =
14607 fake_factory->last_stream_request();
wezca1070932016-05-26 20:30:5214608 ASSERT_TRUE(fake_request);
[email protected]bf828982013-08-14 18:01:4714609 EXPECT_EQ(LOW, fake_request->priority());
14610
14611 trans.SetPriority(LOWEST);
wezca1070932016-05-26 20:30:5214612 ASSERT_TRUE(fake_request);
[email protected]bf828982013-08-14 18:01:4714613 EXPECT_EQ(LOWEST, fake_request->priority());
14614}
14615
[email protected]e86839fd2013-08-14 18:29:0314616// Make sure that HttpNetworkTransaction passes on its priority
14617// updates to its stream.
bncd16676a2016-07-20 16:23:0114618TEST_F(HttpNetworkTransactionTest, SetStreamPriority) {
danakj1fd259a02016-04-16 03:17:0914619 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenkee65e7af2015-10-13 17:16:4214620 HttpNetworkSessionPeer peer(session.get());
[email protected]e86839fd2013-08-14 18:29:0314621 FakeStreamFactory* fake_factory = new FakeStreamFactory();
danakj1fd259a02016-04-16 03:17:0914622 peer.SetHttpStreamFactory(std::unique_ptr<HttpStreamFactory>(fake_factory));
[email protected]e86839fd2013-08-14 18:29:0314623
dcheng48459ac22014-08-26 00:46:4114624 HttpNetworkTransaction trans(LOW, session.get());
[email protected]e86839fd2013-08-14 18:29:0314625
14626 HttpRequestInfo request;
14627 TestCompletionCallback callback;
14628 EXPECT_EQ(ERR_IO_PENDING,
14629 trans.Start(&request, callback.callback(), BoundNetLog()));
14630
14631 base::WeakPtr<FakeStreamRequest> fake_request =
14632 fake_factory->last_stream_request();
wezca1070932016-05-26 20:30:5214633 ASSERT_TRUE(fake_request);
[email protected]e86839fd2013-08-14 18:29:0314634 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
wezca1070932016-05-26 20:30:5214635 ASSERT_TRUE(fake_stream);
[email protected]e86839fd2013-08-14 18:29:0314636 EXPECT_EQ(LOW, fake_stream->priority());
14637
14638 trans.SetPriority(LOWEST);
14639 EXPECT_EQ(LOWEST, fake_stream->priority());
14640}
14641
bncd16676a2016-07-20 16:23:0114642TEST_F(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
[email protected]831e4a32013-11-14 02:14:4414643 // The same logic needs to be tested for both ws: and wss: schemes, but this
14644 // test is already parameterised on NextProto, so it uses a loop to verify
14645 // that the different schemes work.
bncce36dca22015-04-21 22:11:2314646 std::string test_cases[] = {"ws://www.example.org/",
14647 "wss://www.example.org/"};
[email protected]831e4a32013-11-14 02:14:4414648 for (size_t i = 0; i < arraysize(test_cases); ++i) {
danakj1fd259a02016-04-16 03:17:0914649 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
mmenkee65e7af2015-10-13 17:16:4214650 HttpNetworkSessionPeer peer(session.get());
[email protected]831e4a32013-11-14 02:14:4414651 FakeStreamFactory* fake_factory = new FakeStreamFactory();
14652 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
[email protected]0191b51c2013-11-18 10:55:2314653 peer.SetHttpStreamFactoryForWebSocket(
danakj1fd259a02016-04-16 03:17:0914654 std::unique_ptr<HttpStreamFactory>(fake_factory));
[email protected]831e4a32013-11-14 02:14:4414655
dcheng48459ac22014-08-26 00:46:4114656 HttpNetworkTransaction trans(LOW, session.get());
[email protected]831e4a32013-11-14 02:14:4414657 trans.SetWebSocketHandshakeStreamCreateHelper(
14658 &websocket_stream_create_helper);
14659
14660 HttpRequestInfo request;
14661 TestCompletionCallback callback;
14662 request.method = "GET";
14663 request.url = GURL(test_cases[i]);
14664
14665 EXPECT_EQ(ERR_IO_PENDING,
14666 trans.Start(&request, callback.callback(), BoundNetLog()));
14667
14668 base::WeakPtr<FakeStreamRequest> fake_request =
14669 fake_factory->last_stream_request();
wezca1070932016-05-26 20:30:5214670 ASSERT_TRUE(fake_request);
[email protected]831e4a32013-11-14 02:14:4414671 EXPECT_EQ(&websocket_stream_create_helper,
14672 fake_request->websocket_stream_create_helper());
14673 }
14674}
14675
[email protected]043b68c82013-08-22 23:41:5214676// Tests that when a used socket is returned to the SSL socket pool, it's closed
14677// if the transport socket pool is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0114678TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
[email protected]043b68c82013-08-22 23:41:5214679 ClientSocketPoolManager::set_max_sockets_per_group(
14680 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14681 ClientSocketPoolManager::set_max_sockets_per_pool(
14682 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14683
14684 // Set up SSL request.
14685
14686 HttpRequestInfo ssl_request;
14687 ssl_request.method = "GET";
bncce36dca22015-04-21 22:11:2314688 ssl_request.url = GURL("https://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214689
14690 MockWrite ssl_writes[] = {
bncce36dca22015-04-21 22:11:2314691 MockWrite(
14692 "GET / HTTP/1.1\r\n"
14693 "Host: www.example.org\r\n"
14694 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214695 };
14696 MockRead ssl_reads[] = {
14697 MockRead("HTTP/1.1 200 OK\r\n"),
14698 MockRead("Content-Length: 11\r\n\r\n"),
14699 MockRead("hello world"),
14700 MockRead(SYNCHRONOUS, OK),
14701 };
14702 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
14703 ssl_writes, arraysize(ssl_writes));
14704 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14705
14706 SSLSocketDataProvider ssl(ASYNC, OK);
14707 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14708
14709 // Set up HTTP request.
14710
14711 HttpRequestInfo http_request;
14712 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314713 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214714
14715 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314716 MockWrite(
14717 "GET / HTTP/1.1\r\n"
14718 "Host: www.example.org\r\n"
14719 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214720 };
14721 MockRead http_reads[] = {
14722 MockRead("HTTP/1.1 200 OK\r\n"),
14723 MockRead("Content-Length: 7\r\n\r\n"),
14724 MockRead("falafel"),
14725 MockRead(SYNCHRONOUS, OK),
14726 };
14727 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14728 http_writes, arraysize(http_writes));
14729 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14730
danakj1fd259a02016-04-16 03:17:0914731 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214732
14733 // Start the SSL request.
14734 TestCompletionCallback ssl_callback;
danakj1fd259a02016-04-16 03:17:0914735 std::unique_ptr<HttpTransaction> ssl_trans(
[email protected]043b68c82013-08-22 23:41:5214736 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14737 ASSERT_EQ(ERR_IO_PENDING,
14738 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
14739 BoundNetLog()));
14740
14741 // Start the HTTP request. Pool should stall.
14742 TestCompletionCallback http_callback;
danakj1fd259a02016-04-16 03:17:0914743 std::unique_ptr<HttpTransaction> http_trans(
[email protected]043b68c82013-08-22 23:41:5214744 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14745 ASSERT_EQ(ERR_IO_PENDING,
14746 http_trans->Start(&http_request, http_callback.callback(),
14747 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114748 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214749
14750 // Wait for response from SSL request.
robpercival214763f2016-07-01 23:27:0114751 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5214752 std::string response_data;
robpercival214763f2016-07-01 23:27:0114753 ASSERT_THAT(ReadTransaction(ssl_trans.get(), &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5214754 EXPECT_EQ("hello world", response_data);
14755
14756 // The SSL socket should automatically be closed, so the HTTP request can
14757 // start.
dcheng48459ac22014-08-26 00:46:4114758 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
14759 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214760
14761 // The HTTP request can now complete.
robpercival214763f2016-07-01 23:27:0114762 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
14763 ASSERT_THAT(ReadTransaction(http_trans.get(), &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5214764 EXPECT_EQ("falafel", response_data);
14765
dcheng48459ac22014-08-26 00:46:4114766 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214767}
14768
14769// Tests that when a SSL connection is established but there's no corresponding
14770// request that needs it, the new socket is closed if the transport socket pool
14771// is stalled on the global socket limit.
bncd16676a2016-07-20 16:23:0114772TEST_F(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
[email protected]043b68c82013-08-22 23:41:5214773 ClientSocketPoolManager::set_max_sockets_per_group(
14774 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14775 ClientSocketPoolManager::set_max_sockets_per_pool(
14776 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
14777
14778 // Set up an ssl request.
14779
14780 HttpRequestInfo ssl_request;
14781 ssl_request.method = "GET";
14782 ssl_request.url = GURL("https://www.foopy.com/");
14783
14784 // No data will be sent on the SSL socket.
14785 StaticSocketDataProvider ssl_data;
14786 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
14787
14788 SSLSocketDataProvider ssl(ASYNC, OK);
14789 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14790
14791 // Set up HTTP request.
14792
14793 HttpRequestInfo http_request;
14794 http_request.method = "GET";
bncce36dca22015-04-21 22:11:2314795 http_request.url = GURL("http://www.example.org/");
[email protected]043b68c82013-08-22 23:41:5214796
14797 MockWrite http_writes[] = {
bncce36dca22015-04-21 22:11:2314798 MockWrite(
14799 "GET / HTTP/1.1\r\n"
14800 "Host: www.example.org\r\n"
14801 "Connection: keep-alive\r\n\r\n"),
[email protected]043b68c82013-08-22 23:41:5214802 };
14803 MockRead http_reads[] = {
14804 MockRead("HTTP/1.1 200 OK\r\n"),
14805 MockRead("Content-Length: 7\r\n\r\n"),
14806 MockRead("falafel"),
14807 MockRead(SYNCHRONOUS, OK),
14808 };
14809 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
14810 http_writes, arraysize(http_writes));
14811 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
14812
danakj1fd259a02016-04-16 03:17:0914813 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]043b68c82013-08-22 23:41:5214814
14815 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
14816 // cancelled when a normal transaction is cancelled.
ttuttle859dc7a2015-04-23 19:42:2914817 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
nharper8cdb0fb2016-04-22 21:34:5914818 http_stream_factory->PreconnectStreams(1, ssl_request);
dcheng48459ac22014-08-26 00:46:4114819 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214820
14821 // Start the HTTP request. Pool should stall.
14822 TestCompletionCallback http_callback;
danakj1fd259a02016-04-16 03:17:0914823 std::unique_ptr<HttpTransaction> http_trans(
[email protected]043b68c82013-08-22 23:41:5214824 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
14825 ASSERT_EQ(ERR_IO_PENDING,
14826 http_trans->Start(&http_request, http_callback.callback(),
14827 BoundNetLog()));
dcheng48459ac22014-08-26 00:46:4114828 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
[email protected]043b68c82013-08-22 23:41:5214829
14830 // The SSL connection will automatically be closed once the connection is
14831 // established, to let the HTTP request start.
robpercival214763f2016-07-01 23:27:0114832 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
[email protected]043b68c82013-08-22 23:41:5214833 std::string response_data;
robpercival214763f2016-07-01 23:27:0114834 ASSERT_THAT(ReadTransaction(http_trans.get(), &response_data), IsOk());
[email protected]043b68c82013-08-22 23:41:5214835 EXPECT_EQ("falafel", response_data);
14836
dcheng48459ac22014-08-26 00:46:4114837 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
[email protected]043b68c82013-08-22 23:41:5214838}
14839
bncd16676a2016-07-20 16:23:0114840TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0914841 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2214842 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0914843 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2214844 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414845
14846 HttpRequestInfo request;
14847 request.method = "POST";
14848 request.url = GURL("http://www.foo.com/");
14849 request.upload_data_stream = &upload_data_stream;
14850 request.load_flags = 0;
14851
danakj1fd259a02016-04-16 03:17:0914852 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14853 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114854 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414855 // Send headers successfully, but get an error while sending the body.
14856 MockWrite data_writes[] = {
14857 MockWrite("POST / HTTP/1.1\r\n"
14858 "Host: www.foo.com\r\n"
14859 "Connection: keep-alive\r\n"
14860 "Content-Length: 3\r\n\r\n"),
14861 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14862 };
14863
14864 MockRead data_reads[] = {
14865 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14866 MockRead("hello world"),
14867 MockRead(SYNCHRONOUS, OK),
14868 };
14869 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14870 arraysize(data_writes));
14871 session_deps_.socket_factory->AddSocketDataProvider(&data);
14872
14873 TestCompletionCallback callback;
14874
14875 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114876 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5414877
14878 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114879 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5414880
14881 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5214882 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5414883
wezca1070932016-05-26 20:30:5214884 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5414885 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
14886
14887 std::string response_data;
14888 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0114889 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5414890 EXPECT_EQ("hello world", response_data);
14891}
14892
14893// This test makes sure the retry logic doesn't trigger when reading an error
14894// response from a server that rejected a POST with a CONNECTION_RESET.
bncd16676a2016-07-20 16:23:0114895TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5414896 PostReadsErrorResponseAfterResetOnReusedSocket) {
danakj1fd259a02016-04-16 03:17:0914897 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
[email protected]02d74a02014-04-23 18:10:5414898 MockWrite data_writes[] = {
14899 MockWrite("GET / HTTP/1.1\r\n"
14900 "Host: www.foo.com\r\n"
14901 "Connection: keep-alive\r\n\r\n"),
14902 MockWrite("POST / HTTP/1.1\r\n"
14903 "Host: www.foo.com\r\n"
14904 "Connection: keep-alive\r\n"
14905 "Content-Length: 3\r\n\r\n"),
14906 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
14907 };
14908
14909 MockRead data_reads[] = {
14910 MockRead("HTTP/1.1 200 Peachy\r\n"
14911 "Content-Length: 14\r\n\r\n"),
14912 MockRead("first response"),
14913 MockRead("HTTP/1.1 400 Not OK\r\n"
14914 "Content-Length: 15\r\n\r\n"),
14915 MockRead("second response"),
14916 MockRead(SYNCHRONOUS, OK),
14917 };
14918 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
14919 arraysize(data_writes));
14920 session_deps_.socket_factory->AddSocketDataProvider(&data);
14921
14922 TestCompletionCallback callback;
14923 HttpRequestInfo request1;
14924 request1.method = "GET";
14925 request1.url = GURL("http://www.foo.com/");
14926 request1.load_flags = 0;
14927
danakj1fd259a02016-04-16 03:17:0914928 std::unique_ptr<HttpTransaction> trans1(
dcheng48459ac22014-08-26 00:46:4114929 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414930 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114931 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5414932
14933 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114934 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5414935
14936 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
wezca1070932016-05-26 20:30:5214937 ASSERT_TRUE(response1);
[email protected]02d74a02014-04-23 18:10:5414938
wezca1070932016-05-26 20:30:5214939 EXPECT_TRUE(response1->headers);
[email protected]02d74a02014-04-23 18:10:5414940 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
14941
14942 std::string response_data1;
14943 rv = ReadTransaction(trans1.get(), &response_data1);
robpercival214763f2016-07-01 23:27:0114944 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5414945 EXPECT_EQ("first response", response_data1);
14946 // Delete the transaction to release the socket back into the socket pool.
14947 trans1.reset();
14948
danakj1fd259a02016-04-16 03:17:0914949 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2214950 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0914951 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2214952 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414953
14954 HttpRequestInfo request2;
14955 request2.method = "POST";
14956 request2.url = GURL("http://www.foo.com/");
14957 request2.upload_data_stream = &upload_data_stream;
14958 request2.load_flags = 0;
14959
danakj1fd259a02016-04-16 03:17:0914960 std::unique_ptr<HttpTransaction> trans2(
dcheng48459ac22014-08-26 00:46:4114961 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414962 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0114963 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5414964
14965 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0114966 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5414967
14968 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
wezca1070932016-05-26 20:30:5214969 ASSERT_TRUE(response2);
[email protected]02d74a02014-04-23 18:10:5414970
wezca1070932016-05-26 20:30:5214971 EXPECT_TRUE(response2->headers);
[email protected]02d74a02014-04-23 18:10:5414972 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
14973
14974 std::string response_data2;
14975 rv = ReadTransaction(trans2.get(), &response_data2);
robpercival214763f2016-07-01 23:27:0114976 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5414977 EXPECT_EQ("second response", response_data2);
14978}
14979
bncd16676a2016-07-20 16:23:0114980TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5414981 PostReadsErrorResponseAfterResetPartialBodySent) {
danakj1fd259a02016-04-16 03:17:0914982 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2214983 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0914984 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2214985 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5414986
14987 HttpRequestInfo request;
14988 request.method = "POST";
14989 request.url = GURL("http://www.foo.com/");
14990 request.upload_data_stream = &upload_data_stream;
14991 request.load_flags = 0;
14992
danakj1fd259a02016-04-16 03:17:0914993 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14994 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4114995 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5414996 // Send headers successfully, but get an error while sending the body.
14997 MockWrite data_writes[] = {
14998 MockWrite("POST / HTTP/1.1\r\n"
14999 "Host: www.foo.com\r\n"
15000 "Connection: keep-alive\r\n"
15001 "Content-Length: 3\r\n\r\n"
15002 "fo"),
15003 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15004 };
15005
15006 MockRead data_reads[] = {
15007 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15008 MockRead("hello world"),
15009 MockRead(SYNCHRONOUS, OK),
15010 };
15011 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15012 arraysize(data_writes));
15013 session_deps_.socket_factory->AddSocketDataProvider(&data);
15014
15015 TestCompletionCallback callback;
15016
15017 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115018 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5415019
15020 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115021 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5415022
15023 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5215024 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5415025
wezca1070932016-05-26 20:30:5215026 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5415027 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15028
15029 std::string response_data;
15030 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0115031 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5415032 EXPECT_EQ("hello world", response_data);
15033}
15034
15035// This tests the more common case than the previous test, where headers and
15036// body are not merged into a single request.
bncd16676a2016-07-20 16:23:0115037TEST_F(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
mmenkecbc2b712014-10-09 20:29:0715038 ChunkedUploadDataStream upload_data_stream(0);
[email protected]02d74a02014-04-23 18:10:5415039
15040 HttpRequestInfo request;
15041 request.method = "POST";
15042 request.url = GURL("http://www.foo.com/");
15043 request.upload_data_stream = &upload_data_stream;
15044 request.load_flags = 0;
15045
danakj1fd259a02016-04-16 03:17:0915046 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15047 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115048 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415049 // Send headers successfully, but get an error while sending the body.
15050 MockWrite data_writes[] = {
15051 MockWrite("POST / HTTP/1.1\r\n"
15052 "Host: www.foo.com\r\n"
15053 "Connection: keep-alive\r\n"
15054 "Transfer-Encoding: chunked\r\n\r\n"),
15055 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15056 };
15057
15058 MockRead data_reads[] = {
15059 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15060 MockRead("hello world"),
15061 MockRead(SYNCHRONOUS, OK),
15062 };
15063 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15064 arraysize(data_writes));
15065 session_deps_.socket_factory->AddSocketDataProvider(&data);
15066
15067 TestCompletionCallback callback;
15068
15069 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115070 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5415071 // Make sure the headers are sent before adding a chunk. This ensures that
15072 // they can't be merged with the body in a single send. Not currently
15073 // necessary since a chunked body is never merged with headers, but this makes
15074 // the test more future proof.
15075 base::RunLoop().RunUntilIdle();
15076
mmenkecbc2b712014-10-09 20:29:0715077 upload_data_stream.AppendData("last chunk", 10, true);
[email protected]02d74a02014-04-23 18:10:5415078
15079 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115080 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5415081
15082 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5215083 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5415084
wezca1070932016-05-26 20:30:5215085 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5415086 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15087
15088 std::string response_data;
15089 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0115090 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5415091 EXPECT_EQ("hello world", response_data);
15092}
15093
bncd16676a2016-07-20 16:23:0115094TEST_F(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0915095 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2215096 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0915097 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2215098 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415099
15100 HttpRequestInfo request;
15101 request.method = "POST";
15102 request.url = GURL("http://www.foo.com/");
15103 request.upload_data_stream = &upload_data_stream;
15104 request.load_flags = 0;
15105
danakj1fd259a02016-04-16 03:17:0915106 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15107 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115108 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415109
15110 MockWrite data_writes[] = {
15111 MockWrite("POST / HTTP/1.1\r\n"
15112 "Host: www.foo.com\r\n"
15113 "Connection: keep-alive\r\n"
15114 "Content-Length: 3\r\n\r\n"),
15115 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15116 };
15117
15118 MockRead data_reads[] = {
15119 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15120 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
15121 MockRead("hello world"),
15122 MockRead(SYNCHRONOUS, OK),
15123 };
15124 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15125 arraysize(data_writes));
15126 session_deps_.socket_factory->AddSocketDataProvider(&data);
15127
15128 TestCompletionCallback callback;
15129
15130 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115131 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5415132
15133 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115134 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5415135
15136 const HttpResponseInfo* response = trans->GetResponseInfo();
wezca1070932016-05-26 20:30:5215137 ASSERT_TRUE(response);
[email protected]02d74a02014-04-23 18:10:5415138
wezca1070932016-05-26 20:30:5215139 EXPECT_TRUE(response->headers);
[email protected]02d74a02014-04-23 18:10:5415140 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
15141
15142 std::string response_data;
15143 rv = ReadTransaction(trans.get(), &response_data);
robpercival214763f2016-07-01 23:27:0115144 EXPECT_THAT(rv, IsOk());
[email protected]02d74a02014-04-23 18:10:5415145 EXPECT_EQ("hello world", response_data);
15146}
15147
bncd16676a2016-07-20 16:23:0115148TEST_F(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0915149 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2215150 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0915151 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2215152 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415153
15154 HttpRequestInfo request;
15155 request.method = "POST";
15156 request.url = GURL("http://www.foo.com/");
15157 request.upload_data_stream = &upload_data_stream;
15158 request.load_flags = 0;
15159
danakj1fd259a02016-04-16 03:17:0915160 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15161 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115162 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415163 // Send headers successfully, but get an error while sending the body.
15164 MockWrite data_writes[] = {
15165 MockWrite("POST / HTTP/1.1\r\n"
15166 "Host: www.foo.com\r\n"
15167 "Connection: keep-alive\r\n"
15168 "Content-Length: 3\r\n\r\n"),
15169 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15170 };
15171
15172 MockRead data_reads[] = {
15173 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
15174 MockRead("hello world"),
15175 MockRead(SYNCHRONOUS, OK),
15176 };
15177 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15178 arraysize(data_writes));
15179 session_deps_.socket_factory->AddSocketDataProvider(&data);
15180
15181 TestCompletionCallback callback;
15182
15183 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115184 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5415185
15186 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115187 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5415188}
15189
bncd16676a2016-07-20 16:23:0115190TEST_F(HttpNetworkTransactionTest,
[email protected]02d74a02014-04-23 18:10:5415191 PostIgnoresNonErrorResponseAfterResetAnd100) {
danakj1fd259a02016-04-16 03:17:0915192 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2215193 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0915194 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2215195 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415196
15197 HttpRequestInfo request;
15198 request.method = "POST";
15199 request.url = GURL("http://www.foo.com/");
15200 request.upload_data_stream = &upload_data_stream;
15201 request.load_flags = 0;
15202
danakj1fd259a02016-04-16 03:17:0915203 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15204 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115205 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415206 // Send headers successfully, but get an error while sending the body.
15207 MockWrite data_writes[] = {
15208 MockWrite("POST / HTTP/1.1\r\n"
15209 "Host: www.foo.com\r\n"
15210 "Connection: keep-alive\r\n"
15211 "Content-Length: 3\r\n\r\n"),
15212 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15213 };
15214
15215 MockRead data_reads[] = {
15216 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
15217 MockRead("HTTP/1.0 302 Redirect\r\n"),
15218 MockRead("Location: http://somewhere-else.com/\r\n"),
15219 MockRead("Content-Length: 0\r\n\r\n"),
15220 MockRead(SYNCHRONOUS, OK),
15221 };
15222 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15223 arraysize(data_writes));
15224 session_deps_.socket_factory->AddSocketDataProvider(&data);
15225
15226 TestCompletionCallback callback;
15227
15228 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115229 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5415230
15231 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115232 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5415233}
15234
bncd16676a2016-07-20 16:23:0115235TEST_F(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
danakj1fd259a02016-04-16 03:17:0915236 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2215237 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0915238 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2215239 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415240
15241 HttpRequestInfo request;
15242 request.method = "POST";
15243 request.url = GURL("http://www.foo.com/");
15244 request.upload_data_stream = &upload_data_stream;
15245 request.load_flags = 0;
15246
danakj1fd259a02016-04-16 03:17:0915247 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15248 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115249 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415250 // Send headers successfully, but get an error while sending the body.
15251 MockWrite data_writes[] = {
15252 MockWrite("POST / HTTP/1.1\r\n"
15253 "Host: www.foo.com\r\n"
15254 "Connection: keep-alive\r\n"
15255 "Content-Length: 3\r\n\r\n"),
15256 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15257 };
15258
15259 MockRead data_reads[] = {
15260 MockRead("HTTP 0.9 rocks!"),
15261 MockRead(SYNCHRONOUS, OK),
15262 };
15263 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15264 arraysize(data_writes));
15265 session_deps_.socket_factory->AddSocketDataProvider(&data);
15266
15267 TestCompletionCallback callback;
15268
15269 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115270 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5415271
15272 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115273 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5415274}
15275
bncd16676a2016-07-20 16:23:0115276TEST_F(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
danakj1fd259a02016-04-16 03:17:0915277 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2215278 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0915279 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2215280 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
[email protected]02d74a02014-04-23 18:10:5415281
15282 HttpRequestInfo request;
15283 request.method = "POST";
15284 request.url = GURL("http://www.foo.com/");
15285 request.upload_data_stream = &upload_data_stream;
15286 request.load_flags = 0;
15287
danakj1fd259a02016-04-16 03:17:0915288 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15289 std::unique_ptr<HttpTransaction> trans(
dcheng48459ac22014-08-26 00:46:4115290 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]02d74a02014-04-23 18:10:5415291 // Send headers successfully, but get an error while sending the body.
15292 MockWrite data_writes[] = {
15293 MockWrite("POST / HTTP/1.1\r\n"
15294 "Host: www.foo.com\r\n"
15295 "Connection: keep-alive\r\n"
15296 "Content-Length: 3\r\n\r\n"),
15297 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
15298 };
15299
15300 MockRead data_reads[] = {
15301 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
15302 MockRead(SYNCHRONOUS, OK),
15303 };
15304 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15305 arraysize(data_writes));
15306 session_deps_.socket_factory->AddSocketDataProvider(&data);
15307
15308 TestCompletionCallback callback;
15309
15310 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115311 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
[email protected]02d74a02014-04-23 18:10:5415312
15313 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115314 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
[email protected]02d74a02014-04-23 18:10:5415315}
15316
Adam Rice425cf122015-01-19 06:18:2415317// Verify that proxy headers are not sent to the destination server when
15318// establishing a tunnel for a secure WebSocket connection.
bncd16676a2016-07-20 16:23:0115319TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
Adam Rice425cf122015-01-19 06:18:2415320 HttpRequestInfo request;
15321 request.method = "GET";
bncce36dca22015-04-21 22:11:2315322 request.url = GURL("wss://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415323 AddWebSocketHeaders(&request.extra_headers);
15324
15325 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315326 session_deps_.proxy_service =
15327 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415328
danakj1fd259a02016-04-16 03:17:0915329 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415330
15331 // Since a proxy is configured, try to establish a tunnel.
15332 MockWrite data_writes[] = {
rsleevidb16bb02015-11-12 23:47:1715333 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15334 "Host: www.example.org:443\r\n"
15335 "Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415336
15337 // After calling trans->RestartWithAuth(), this is the request we should
15338 // be issuing -- the final header line contains the credentials.
rsleevidb16bb02015-11-12 23:47:1715339 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
15340 "Host: www.example.org:443\r\n"
15341 "Proxy-Connection: keep-alive\r\n"
15342 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415343
rsleevidb16bb02015-11-12 23:47:1715344 MockWrite("GET / HTTP/1.1\r\n"
15345 "Host: www.example.org\r\n"
15346 "Connection: Upgrade\r\n"
15347 "Upgrade: websocket\r\n"
15348 "Origin: http://www.example.org\r\n"
15349 "Sec-WebSocket-Version: 13\r\n"
15350 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415351 };
15352
15353 // The proxy responds to the connect with a 407, using a persistent
15354 // connection.
15355 MockRead data_reads[] = {
15356 // No credentials.
15357 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
15358 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
mmenkee71e15332015-10-07 16:39:5415359 MockRead("Content-Length: 0\r\n"),
15360 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
Adam Rice425cf122015-01-19 06:18:2415361
15362 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15363
15364 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15365 MockRead("Upgrade: websocket\r\n"),
15366 MockRead("Connection: Upgrade\r\n"),
15367 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15368 };
15369
15370 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15371 arraysize(data_writes));
15372 session_deps_.socket_factory->AddSocketDataProvider(&data);
15373 SSLSocketDataProvider ssl(ASYNC, OK);
15374 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15375
danakj1fd259a02016-04-16 03:17:0915376 std::unique_ptr<HttpTransaction> trans(
Adam Rice425cf122015-01-19 06:18:2415377 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15378 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15379 trans->SetWebSocketHandshakeStreamCreateHelper(
15380 &websocket_stream_create_helper);
15381
15382 {
15383 TestCompletionCallback callback;
15384
15385 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115386 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2415387
15388 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115389 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2415390 }
15391
15392 const HttpResponseInfo* response = trans->GetResponseInfo();
15393 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5215394 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2415395 EXPECT_EQ(407, response->headers->response_code());
15396
15397 {
15398 TestCompletionCallback callback;
15399
15400 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
15401 callback.callback());
robpercival214763f2016-07-01 23:27:0115402 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2415403
15404 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115405 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2415406 }
15407
15408 response = trans->GetResponseInfo();
15409 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5215410 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2415411
15412 EXPECT_EQ(101, response->headers->response_code());
15413
15414 trans.reset();
15415 session->CloseAllConnections();
15416}
15417
15418// Verify that proxy headers are not sent to the destination server when
15419// establishing a tunnel for an insecure WebSocket connection.
15420// This requires the authentication info to be injected into the auth cache
15421// due to crbug.com/395064
15422// TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
bncd16676a2016-07-20 16:23:0115423TEST_F(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
Adam Rice425cf122015-01-19 06:18:2415424 HttpRequestInfo request;
15425 request.method = "GET";
bncce36dca22015-04-21 22:11:2315426 request.url = GURL("ws://www.example.org/");
Adam Rice425cf122015-01-19 06:18:2415427 AddWebSocketHeaders(&request.extra_headers);
15428
15429 // Configure against proxy server "myproxy:70".
rdsmith82957ad2015-09-16 19:42:0315430 session_deps_.proxy_service =
15431 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70");
Adam Rice425cf122015-01-19 06:18:2415432
danakj1fd259a02016-04-16 03:17:0915433 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
Adam Rice425cf122015-01-19 06:18:2415434
15435 MockWrite data_writes[] = {
15436 // Try to establish a tunnel for the WebSocket connection, with
15437 // credentials. Because WebSockets have a separate set of socket pools,
15438 // they cannot and will not use the same TCP/IP connection as the
15439 // preflight HTTP request.
15440 MockWrite(
bncce36dca22015-04-21 22:11:2315441 "CONNECT www.example.org:80 HTTP/1.1\r\n"
15442 "Host: www.example.org:80\r\n"
Adam Rice425cf122015-01-19 06:18:2415443 "Proxy-Connection: keep-alive\r\n"
15444 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15445
15446 MockWrite(
15447 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:2315448 "Host: www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415449 "Connection: Upgrade\r\n"
15450 "Upgrade: websocket\r\n"
bncce36dca22015-04-21 22:11:2315451 "Origin: http://www.example.org\r\n"
Adam Rice425cf122015-01-19 06:18:2415452 "Sec-WebSocket-Version: 13\r\n"
15453 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
15454 };
15455
15456 MockRead data_reads[] = {
15457 // HTTP CONNECT with credentials.
15458 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
15459
15460 // WebSocket connection established inside tunnel.
15461 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
15462 MockRead("Upgrade: websocket\r\n"),
15463 MockRead("Connection: Upgrade\r\n"),
15464 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
15465 };
15466
15467 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15468 arraysize(data_writes));
15469 session_deps_.socket_factory->AddSocketDataProvider(&data);
15470
15471 session->http_auth_cache()->Add(
15472 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
15473 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
15474
danakj1fd259a02016-04-16 03:17:0915475 std::unique_ptr<HttpTransaction> trans(
Adam Rice425cf122015-01-19 06:18:2415476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15477 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
15478 trans->SetWebSocketHandshakeStreamCreateHelper(
15479 &websocket_stream_create_helper);
15480
15481 TestCompletionCallback callback;
15482
15483 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
robpercival214763f2016-07-01 23:27:0115484 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
Adam Rice425cf122015-01-19 06:18:2415485
15486 rv = callback.WaitForResult();
robpercival214763f2016-07-01 23:27:0115487 EXPECT_THAT(rv, IsOk());
Adam Rice425cf122015-01-19 06:18:2415488
15489 const HttpResponseInfo* response = trans->GetResponseInfo();
15490 ASSERT_TRUE(response);
wezca1070932016-05-26 20:30:5215491 ASSERT_TRUE(response->headers);
Adam Rice425cf122015-01-19 06:18:2415492
15493 EXPECT_EQ(101, response->headers->response_code());
15494
15495 trans.reset();
15496 session->CloseAllConnections();
15497}
15498
bncd16676a2016-07-20 16:23:0115499TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
danakj1fd259a02016-04-16 03:17:0915500 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2215501 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0915502 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2215503 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215504
15505 HttpRequestInfo request;
15506 request.method = "POST";
15507 request.url = GURL("http://www.foo.com/");
15508 request.upload_data_stream = &upload_data_stream;
15509
danakj1fd259a02016-04-16 03:17:0915510 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15511 std::unique_ptr<HttpTransaction> trans(
sclittlefb249892015-09-10 21:33:2215512 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15513 MockWrite data_writes[] = {
15514 MockWrite("POST / HTTP/1.1\r\n"
15515 "Host: www.foo.com\r\n"
15516 "Connection: keep-alive\r\n"
15517 "Content-Length: 3\r\n\r\n"),
15518 MockWrite("foo"),
15519 };
15520
15521 MockRead data_reads[] = {
15522 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15523 MockRead(SYNCHRONOUS, OK),
15524 };
15525 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15526 arraysize(data_writes));
15527 session_deps_.socket_factory->AddSocketDataProvider(&data);
15528
15529 TestCompletionCallback callback;
15530
15531 EXPECT_EQ(ERR_IO_PENDING,
15532 trans->Start(&request, callback.callback(), BoundNetLog()));
robpercival214763f2016-07-01 23:27:0115533 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2215534
15535 std::string response_data;
robpercival214763f2016-07-01 23:27:0115536 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2215537
15538 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15539 trans->GetTotalSentBytes());
15540 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15541 trans->GetTotalReceivedBytes());
15542}
15543
bncd16676a2016-07-20 16:23:0115544TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
danakj1fd259a02016-04-16 03:17:0915545 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
olli.raula6df48b2a2015-11-26 07:40:2215546 element_readers.push_back(
danakj1fd259a02016-04-16 03:17:0915547 base::WrapUnique(new UploadBytesElementReader("foo", 3)));
olli.raula6df48b2a2015-11-26 07:40:2215548 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
sclittlefb249892015-09-10 21:33:2215549
15550 HttpRequestInfo request;
15551 request.method = "POST";
15552 request.url = GURL("http://www.foo.com/");
15553 request.upload_data_stream = &upload_data_stream;
15554
danakj1fd259a02016-04-16 03:17:0915555 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15556 std::unique_ptr<HttpTransaction> trans(
sclittlefb249892015-09-10 21:33:2215557 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15558 MockWrite data_writes[] = {
15559 MockWrite("POST / HTTP/1.1\r\n"
15560 "Host: www.foo.com\r\n"
15561 "Connection: keep-alive\r\n"
15562 "Content-Length: 3\r\n\r\n"),
15563 MockWrite("foo"),
15564 };
15565
15566 MockRead data_reads[] = {
15567 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
15568 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15569 MockRead(SYNCHRONOUS, OK),
15570 };
15571 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15572 arraysize(data_writes));
15573 session_deps_.socket_factory->AddSocketDataProvider(&data);
15574
15575 TestCompletionCallback callback;
15576
15577 EXPECT_EQ(ERR_IO_PENDING,
15578 trans->Start(&request, callback.callback(), BoundNetLog()));
robpercival214763f2016-07-01 23:27:0115579 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2215580
15581 std::string response_data;
robpercival214763f2016-07-01 23:27:0115582 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2215583
15584 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15585 trans->GetTotalSentBytes());
15586 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15587 trans->GetTotalReceivedBytes());
15588}
15589
bncd16676a2016-07-20 16:23:0115590TEST_F(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
sclittlefb249892015-09-10 21:33:2215591 ChunkedUploadDataStream upload_data_stream(0);
15592
15593 HttpRequestInfo request;
15594 request.method = "POST";
15595 request.url = GURL("http://www.foo.com/");
15596 request.upload_data_stream = &upload_data_stream;
15597
danakj1fd259a02016-04-16 03:17:0915598 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15599 std::unique_ptr<HttpTransaction> trans(
sclittlefb249892015-09-10 21:33:2215600 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
15601 // Send headers successfully, but get an error while sending the body.
15602 MockWrite data_writes[] = {
15603 MockWrite("POST / HTTP/1.1\r\n"
15604 "Host: www.foo.com\r\n"
15605 "Connection: keep-alive\r\n"
15606 "Transfer-Encoding: chunked\r\n\r\n"),
15607 MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"),
15608 };
15609
15610 MockRead data_reads[] = {
15611 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
15612 MockRead(SYNCHRONOUS, OK),
15613 };
15614 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
15615 arraysize(data_writes));
15616 session_deps_.socket_factory->AddSocketDataProvider(&data);
15617
15618 TestCompletionCallback callback;
15619
15620 EXPECT_EQ(ERR_IO_PENDING,
15621 trans->Start(&request, callback.callback(), BoundNetLog()));
15622
15623 base::RunLoop().RunUntilIdle();
15624 upload_data_stream.AppendData("f", 1, false);
15625
15626 base::RunLoop().RunUntilIdle();
15627 upload_data_stream.AppendData("oo", 2, true);
15628
robpercival214763f2016-07-01 23:27:0115629 EXPECT_THAT(callback.WaitForResult(), IsOk());
sclittlefb249892015-09-10 21:33:2215630
15631 std::string response_data;
robpercival214763f2016-07-01 23:27:0115632 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
sclittlefb249892015-09-10 21:33:2215633
15634 EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)),
15635 trans->GetTotalSentBytes());
15636 EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)),
15637 trans->GetTotalReceivedBytes());
15638}
15639
nharperb7441ef2016-01-25 23:54:1415640#if !defined(OS_IOS)
bncd16676a2016-07-20 16:23:0115641TEST_F(HttpNetworkTransactionTest, TokenBindingSpdy) {
nharperb7441ef2016-01-25 23:54:1415642 const std::string https_url = "https://www.example.com";
15643 HttpRequestInfo request;
15644 request.url = GURL(https_url);
15645 request.method = "GET";
15646
15647 SSLSocketDataProvider ssl(ASYNC, OK);
15648 ssl.token_binding_negotiated = true;
15649 ssl.token_binding_key_param = TB_PARAM_ECDSAP256;
bnc3cf2a592016-08-11 14:48:3615650 ssl.next_proto = kProtoHTTP2;
nharperb7441ef2016-01-25 23:54:1415651 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15652
bnc42331402016-07-25 13:36:1515653 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
bncdf80d44fd2016-07-15 20:27:4115654 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
15655 MockRead reads[] = {CreateMockRead(resp), CreateMockRead(body),
nharperb7441ef2016-01-25 23:54:1415656 MockRead(ASYNC, ERR_IO_PENDING)};
15657 StaticSocketDataProvider data(reads, arraysize(reads), nullptr, 0);
15658 session_deps_.socket_factory->AddSocketDataProvider(&data);
15659 session_deps_.channel_id_service.reset(new ChannelIDService(
15660 new DefaultChannelIDStore(nullptr), base::ThreadTaskRunnerHandle::Get()));
danakj1fd259a02016-04-16 03:17:0915661 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
nharperb7441ef2016-01-25 23:54:1415662
15663 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15664 TestCompletionCallback callback;
15665 EXPECT_EQ(ERR_IO_PENDING,
15666 trans.Start(&request, callback.callback(), BoundNetLog()));
fdoray92e35a72016-06-10 15:54:5515667 base::RunLoop().RunUntilIdle();
nharperb7441ef2016-01-25 23:54:1415668
15669 EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy);
15670 HttpRequestHeaders headers;
15671 ASSERT_TRUE(trans.GetFullRequestHeaders(&headers));
15672 EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding));
15673}
15674#endif // !defined(OS_IOS)
15675
[email protected]89ceba9a2009-03-21 03:46:0615676} // namespace net